diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index ba428c577..f25aee19e 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1352,6 +1352,7 @@ server_side_occlusion_culling (Server side occlusion culling) bool true # LOOKUP_NODES_LIMIT: 16 (limits get_node call client-side to # csm_restriction_noderange) # READ_PLAYERINFO: 32 (disable get_player_names call client-side) +# THIRD_PARTY_MODS: 256 (disable loading third-party CSMs) csm_restriction_flags (Client side modding restrictions) int 62 # If the CSM restriction for node range is enabled, get_node calls are limited diff --git a/multicraft.conf.example b/multicraft.conf.example index 4305cada9..7fe0392fc 100644 --- a/multicraft.conf.example +++ b/multicraft.conf.example @@ -1611,6 +1611,7 @@ # LOOKUP_NODES_LIMIT: 16 (limits get_node call client-side to # csm_restriction_noderange) # READ_PLAYERINFO: 32 (disable get_player_names call client-side) +# THIRD_PARTY_MODS: 256 (disable loading third-party client-provided mods) # type: int # csm_restriction_flags = 60 diff --git a/src/client/client.cpp b/src/client/client.cpp index ce0357fde..b0e8b92e7 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -164,33 +164,35 @@ void Client::loadMods() scanModIntoMemory(BUILTIN_MOD_NAME, getBuiltinLuaPath()); m_script->loadModFromMemory(BUILTIN_MOD_NAME); - ClientModConfiguration modconf(getClientModsLuaPath()); - m_mods = modconf.getMods(); - // complain about mods with unsatisfied dependencies - if (!modconf.isConsistent()) { - modconf.printUnsatisfiedModsError(); - return; - } - - // Print mods - infostream << "Client loading mods: "; - for (const ModSpec &mod : m_mods) - infostream << mod.name << " "; - infostream << std::endl; - - // Load "mod" scripts - for (const ModSpec &mod : m_mods) { - if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) { - throw ModError("Error loading mod \"" + mod.name + - "\": Mod name does not follow naming conventions: " - "Only characters [a-z0-9_] are allowed."); + if (!checkCSMRestrictionFlag(CSMRestrictionFlags::CSM_RF_THIRD_PARTY_MODS)) { + ClientModConfiguration modconf(getClientModsLuaPath()); + m_mods = modconf.getMods(); + // complain about mods with unsatisfied dependencies + if (!modconf.isConsistent()) { + modconf.printUnsatisfiedModsError(); + return; } - scanModIntoMemory(mod.name, mod.path); - } - // Run them - for (const ModSpec &mod : m_mods) - m_script->loadModFromMemory(mod.name); + // Print mods + infostream << "Client loading mods: "; + for (const ModSpec &mod : m_mods) + infostream << mod.name << " "; + infostream << std::endl; + + // Load "mod" scripts + for (const ModSpec &mod : m_mods) { + if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) { + throw ModError("Error loading mod \"" + mod.name + + "\": Mod name does not follow naming conventions: " + "Only characters [a-z0-9_] are allowed."); + } + scanModIntoMemory(mod.name, mod.path); + } + + // Run them + for (const ModSpec &mod : m_mods) + m_script->loadModFromMemory(mod.name); + } // Mods are done loading. Unlock callbacks m_mods_loaded = true; diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 4cb21a5db..9eb91ffae 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -1051,6 +1051,7 @@ enum CSMRestrictionFlags : u64 { CSM_RF_READ_NODEDEFS = 0x00000008, // Disable nodedef lookups CSM_RF_LOOKUP_NODES = 0x00000010, // Limit node lookups CSM_RF_READ_PLAYERINFO = 0x00000020, // Disable player info lookups + CSM_RF_THIRD_PARTY_MODS = 0x00000100, // Don't load third-party CSMs CSM_RF_ALL = 0xFFFFFFFF, }; diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 85f988075..17f3645b8 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -56,6 +56,7 @@ const static CSMFlagDesc flagdesc_csm_restriction[] = { {"read_nodedefs", CSM_RF_READ_NODEDEFS}, {"lookup_nodes", CSM_RF_LOOKUP_NODES}, {"read_playerinfo", CSM_RF_READ_PLAYERINFO}, + {"third_party_mods", CSM_RF_THIRD_PARTY_MODS}, {NULL, 0} };