Skip to content

Commit

Permalink
[CSM] Client side modding
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nerzhul committed Mar 13, 2017
1 parent c9492b4 commit 2efae3f
Show file tree
Hide file tree
Showing 37 changed files with 488 additions and 64 deletions.
22 changes: 22 additions & 0 deletions builtin/client/init.lua
@@ -0,0 +1,22 @@
-- Minetest: builtin/client/init.lua
local scriptpath = core.get_builtin_path()..DIR_DELIM
local clientpath = scriptpath.."client"..DIR_DELIM

dofile(clientpath .. "register.lua")

-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_shutdown(function()
print("shutdown client")
end)

-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_receiving_chat_messages(function(message)
print("Received message " .. message)
return false
end)

-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_sending_chat_messages(function(message)
print("Sending message " .. message)
return false
end)
62 changes: 62 additions & 0 deletions builtin/client/register.lua
@@ -0,0 +1,62 @@

core.callback_origins = {}

function core.run_callbacks(callbacks, mode, ...)
assert(type(callbacks) == "table")
local cb_len = #callbacks
if cb_len == 0 then
if mode == 2 or mode == 3 then
return true
elseif mode == 4 or mode == 5 then
return false
end
end
local ret
for i = 1, cb_len do
local cb_ret = callbacks[i](...)

if mode == 0 and i == 1 or mode == 1 and i == cb_len then
ret = cb_ret
elseif mode == 2 then
if not cb_ret or i == 1 then
ret = cb_ret
end
elseif mode == 3 then
if cb_ret then
return cb_ret
end
ret = cb_ret
elseif mode == 4 then
if (cb_ret and not ret) or i == 1 then
ret = cb_ret
end
elseif mode == 5 and cb_ret then
return cb_ret
end
end
return ret
end

--
-- Callback registration
--

local function make_registration()
local t = {}
local registerfunc = function(func)
t[#t + 1] = func
core.callback_origins[func] = {
mod = core.get_current_modname() or "??",
name = debug.getinfo(1, "n").name or "??"
}
--local origin = core.callback_origins[func]
--print(origin.name .. ": " .. origin.mod .. " registering cbk " .. tostring(func))
end
return t, registerfunc
end

core.registered_on_shutdown, core.register_on_shutdown = make_registration()
core.registered_on_receiving_chat_messages, core.register_on_receiving_chat_messages = make_registration()
core.registered_on_sending_chat_messages, core.register_on_sending_chat_messages = make_registration()


3 changes: 3 additions & 0 deletions builtin/init.lua
Expand Up @@ -27,6 +27,7 @@ minetest = core
-- Load other files
local scriptdir = core.get_builtin_path() .. DIR_DELIM
local gamepath = scriptdir .. "game" .. DIR_DELIM
local clientpath = scriptdir .. "client" .. DIR_DELIM
local commonpath = scriptdir .. "common" .. DIR_DELIM
local asyncpath = scriptdir .. "async" .. DIR_DELIM

Expand All @@ -45,6 +46,8 @@ elseif INIT == "mainmenu" then
end
elseif INIT == "async" then
dofile(asyncpath .. "init.lua")
elseif INIT == "client" then
dofile(clientpath .. "init.lua")
else
error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT)))
end
45 changes: 35 additions & 10 deletions src/client.cpp
Expand Up @@ -32,28 +32,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client.h"
#include "network/clientopcodes.h"
#include "filesys.h"
#include "porting.h"
#include "mapblock_mesh.h"
#include "mapblock.h"
#include "minimap.h"
#include "settings.h"
#include "mods.h"
#include "profiler.h"
#include "gettext.h"
#include "log.h"
#include "nodemetadata.h"
#include "itemdef.h"
#include "shader.h"
#include "clientmap.h"
#include "clientmedia.h"
#include "sound.h"
#include "IMeshCache.h"
#include "config.h"
#include "version.h"
#include "drawscene.h"
#include "database-sqlite3.h"
#include "serialization.h"
#include "guiscalingfilter.h"
#include "raycast.h"
#include "script/clientscripting.h"

extern gui::IGUIEnvironment* guienv;

Expand Down Expand Up @@ -269,17 +261,45 @@ Client::Client(
m_cache_use_tangent_vertices = m_cache_enable_shaders && (
g_settings->getBool("enable_bumpmapping") ||
g_settings->getBool("enable_parallax_occlusion"));

m_script = new ClientScripting(this);
}

void Client::initMods()
{
std::string script_path = getBuiltinLuaPath() + DIR_DELIM "init.lua";

m_script->loadMod(script_path, BUILTIN_MOD_NAME);
}

const std::string Client::getBuiltinLuaPath()
{
return porting::path_share + DIR_DELIM + "builtin";
}

const std::vector<ModSpec>& Client::getMods() const
{
static std::vector<ModSpec> client_modspec_temp;
return client_modspec_temp;
}

const ModSpec* Client::getModSpec(const std::string &modname) const
{
return NULL;
}

void Client::Stop()
{
m_script->on_shutdown();
//request all client managed threads to stop
m_mesh_update_thread.stop();
// Save local server map
if (m_localdb) {
infostream << "Local map saving ended." << std::endl;
m_localdb->endSave();
}

delete m_script;
}

bool Client::isShutdown()
Expand Down Expand Up @@ -1553,6 +1573,11 @@ void Client::typeChatMessage(const std::wstring &message)
if(message == L"")
return;

// If message was ate by script API, don't send it to server
if (m_script->on_sending_message(wide_to_utf8(message))) {
return;
}

// Send to others
sendChatMessage(message);

Expand Down
10 changes: 10 additions & 0 deletions src/client.h
Expand Up @@ -305,6 +305,8 @@ class PacketCounter
std::map<u16, u16> m_packets;
};

class ClientScripting;

class Client : public con::PeerHandler, public InventoryManager, public IGameDef
{
public:
Expand All @@ -328,6 +330,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef

~Client();

void initMods();

/*
request all threads managed by client to be stopped
*/
Expand Down Expand Up @@ -428,6 +432,10 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
ClientEnvironment& getEnv() { return m_env; }
ITextureSource *tsrc() { return getTextureSource(); }
ISoundManager *sound() { return getSoundManager(); }
static const std::string getBuiltinLuaPath();

virtual const std::vector<ModSpec> &getMods() const;
virtual const ModSpec* getModSpec(const std::string &modname) const;

// Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
void removeNode(v3s16 p);
Expand Down Expand Up @@ -692,6 +700,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
bool m_cache_enable_shaders;
bool m_cache_use_tangent_vertices;

ClientScripting *m_script;

DISABLE_CLASS_COPY(Client);
};

Expand Down
2 changes: 1 addition & 1 deletion src/content_abm.cpp
Expand Up @@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "mapblock.h" // For getNodeBlockPos
#include "map.h"
#include "scripting_game.h"
#include "serverscripting.h"
#include "log.h"

void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) {
Expand Down
2 changes: 1 addition & 1 deletion src/content_sao.cpp
Expand Up @@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h"
#include "remoteplayer.h"
#include "server.h"
#include "scripting_game.h"
#include "serverscripting.h"
#include "genericobject.h"

std::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
Expand Down
2 changes: 1 addition & 1 deletion src/emerge.cpp
Expand Up @@ -40,7 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mg_schematic.h"
#include "nodedef.h"
#include "profiler.h"
#include "scripting_game.h"
#include "serverscripting.h"
#include "server.h"
#include "serverobject.h"
#include "settings.h"
Expand Down
2 changes: 1 addition & 1 deletion src/environment.cpp
Expand Up @@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h"
#include "collision.h"
#include "serverobject.h"
#include "scripting_game.h"
#include "serverscripting.h"
#include "server.h"
#include "daynightratio.h"
#include "emerge.h"
Expand Down
2 changes: 2 additions & 0 deletions src/game.cpp
Expand Up @@ -2222,6 +2222,8 @@ bool Game::connectToServer(const std::string &playername,

fps_control.last_time = device->getTimer()->getTime();

client->initMods();

while (device->run()) {

limitFps(&fps_control, &dtime);
Expand Down
7 changes: 6 additions & 1 deletion src/gamedef.h
Expand Up @@ -39,6 +39,7 @@ namespace irr { namespace scene {
class ISceneManager;
}}

struct ModSpec;
/*
An interface for fetching game-global definitions like tool and
mapnode properties
Expand Down Expand Up @@ -68,7 +69,11 @@ class IGameDef
ICraftDefManager *cdef() { return getCraftDefManager(); }

MtEventManager *event() { return getEventManager(); }
IRollbackManager *rollback() { return getRollbackManager();}
IRollbackManager *rollback() { return getRollbackManager(); }

virtual const std::vector<ModSpec> &getMods() const = 0;
virtual const ModSpec* getModSpec(const std::string &modname) const = 0;
virtual std::string getWorldPath() const { return ""; }
};

#endif
Expand Down
2 changes: 1 addition & 1 deletion src/guiFormSpecMenu.cpp
Expand Up @@ -42,7 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h"
#include "gettime.h"
#include "gettext.h"
#include "scripting_game.h"
#include "serverscripting.h"
#include "porting.h"
#include "settings.h"
#include "client.h"
Expand Down
2 changes: 1 addition & 1 deletion src/inventorymanager.cpp
Expand Up @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventorymanager.h"
#include "log.h"
#include "serverenvironment.h"
#include "scripting_game.h"
#include "serverscripting.h"
#include "serverobject.h"
#include "settings.h"
#include "craftdef.h"
Expand Down
6 changes: 5 additions & 1 deletion src/network/clientpackethandler.cpp
Expand Up @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server.h"
#include "util/strfnd.h"
#include "network/clientopcodes.h"
#include "script/clientscripting.h"
#include "util/serialize.h"
#include "util/srp.h"
#include "tileanimation.h"
Expand Down Expand Up @@ -411,7 +412,10 @@ void Client::handleCommand_ChatMessage(NetworkPacket* pkt)
message += (wchar_t)read_wchar;
}

m_chat_queue.push(message);
// If chat message not consummed by client lua API
if (!m_script->on_receiving_message(wide_to_utf8(message))) {
m_chat_queue.push(message);
}
}

void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
Expand Down
2 changes: 1 addition & 1 deletion src/network/serverpackethandler.cpp
Expand Up @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h"
#include "player.h"
#include "rollback_interface.h"
#include "scripting_game.h"
#include "serverscripting.h"
#include "settings.h"
#include "tool.h"
#include "version.h"
Expand Down
7 changes: 4 additions & 3 deletions src/script/CMakeLists.txt
Expand Up @@ -3,16 +3,17 @@ add_subdirectory(cpp_api)
add_subdirectory(lua_api)

# Used by server and client
set(common_SCRIPT_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/scripting_game.cpp
set(common_SCRIPT_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/serverscripting.cpp
${common_SCRIPT_COMMON_SRCS}
${common_SCRIPT_CPP_API_SRCS}
${common_SCRIPT_LUA_API_SRCS}
PARENT_SCOPE)

# Used by client only
set(client_SCRIPT_SRCS
set(client_SCRIPT_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/scripting_mainmenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/clientscripting.cpp
${client_SCRIPT_COMMON_SRCS}
${client_SCRIPT_CPP_API_SRCS}
${client_SCRIPT_LUA_API_SRCS}
Expand Down

0 comments on commit 2efae3f

Please sign in to comment.