-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add a client side mod dialog #16001
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add a client side mod dialog #16001
Conversation
Using this dialog you have the ability to enable or disable client mods without manually editing the file.
Note that the future of CSMs is somewhat uncertain (they have been perpetually experimental since their introduction and have not seen any significant updates in recent years), so I'd be wary of spending lots of time on them. Personally I'm not very interested in advancing them at the moment, especially given that SSCSM will be designed independently from the ground up. |
Since they exist in the game, a simple button like this shouldn't be an issue imo, we can always remove it easily later, but its already been quite a few years with the csms in this middle state, if yall aint gonna finish them then atleast let us make them slightly more useable |
Any updates on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the concept. Let's unify some code to reduce long-term maintenance efforts and we're good to go. Even though the fate of CSM's is uncertain, I believe this is a helpful dialogue for the days to come.
for i=1,#clientmods,1 do | ||
clientmods[i].type = "mod" | ||
clientmods[i].loc = "global" | ||
clientmods[i].is_clientside = true | ||
retval[#retval + 1] = clientmods[i] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tables are references, thus this shorter version is possible:
for i=1,#clientmods,1 do | |
clientmods[i].type = "mod" | |
clientmods[i].loc = "global" | |
clientmods[i].is_clientside = true | |
retval[#retval + 1] = clientmods[i] | |
end | |
for _, mod in ipairs(clientmods) do | |
mod.type = "mod" | |
mod.loc = "global" | |
mod.is_clientside = true | |
end | |
retval = clientmods |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The retval
variable becomes unnecessary, does it not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, by how it's currently used, it's a duplicate.
if element ~= nil then | ||
element.enabled = value ~= "false" and value ~= "nil" and value | ||
else | ||
core.log("info", "Clientmod: " .. key .. " " .. dump(value) .. " but not found") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
core.log("info", "Clientmod: " .. key .. " " .. dump(value) .. " but not found") | |
core.log("info", "Client Mod: Cannot find " .. key .. ", " .. dump(value)) |
local filename = modpath .. | ||
DIR_DELIM .. "mods.conf" | ||
|
||
local conffile = Settings(filename) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local filename = modpath .. | |
DIR_DELIM .. "mods.conf" | |
local conffile = Settings(filename) | |
local conffile = Settings(modpath .. DIR_DELIM .. "mods.conf") |
--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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: you may use the short SPDX-License-Identifier notation instead to avoid this boilerplate. Ctrl+F in the other code for examples.
end | ||
|
||
if fields.btn_csm_mgr_mp_enable ~= nil or fields.btn_csm_mgr_mp_disable ~= nil then | ||
pkgmgr.enable_mod({data = {list = packages, selected_mod = tab_selected_pkg}}, fields.btn_csm_mgr_mp_enable ~= nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines too long. Please keep them below 95 characters.
https://docs.luanti.org/for-engine-devs/code-style-guidelines/#dont-let-things-get-too-large
return true | ||
end | ||
|
||
if fields["btn_csm_mgr_rename_modpack"] ~= nil then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if fields["btn_csm_mgr_rename_modpack"] ~= nil then | |
if fields.btn_csm_mgr_rename_modpack then |
The same for the other occurrences. It makes the code look more consistent. Currently you're mixing two different styles.
if modname_valid(mod.name) then | ||
conffile:set("load_mod_" .. mod.name, | ||
mod.enabled and "true" or "false") | ||
elseif mod.enabled then | ||
gamedata.errormessage = fgettext_ne("Failed to enable clientmod" .. | ||
" \"$1\" as it contains disallowed characters. " .. | ||
"Only characters [a-z0-9_] are allowed.", | ||
mod.name) | ||
end | ||
mods["load_mod_" .. mod.name] = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate of dlg_config_world.lua
. Please re-use existing code. This dialogue already mentions that it's about Client Mods, thus the error message (Failed to enable mod [...]
(that is used there) should be good enough.
Example:
function pkgmgr.foobar_insert_my_mods(mods_ret, packages, conffile, cb_may_add)
for _, mod in ipairs(packages) do
if cb_may_add(mod) then
-- same code here
end
end
end
-- for CSM:
pkgmgr.foobar_insert_my_mods(mods, packages_raw, conffile, function(mod)
return mod.is_clientside
end
-- for Server Mods: (dlg_config_world.lua)
pkgmgr.foobar_insert_my_mods(mods, packages_raw, conffile, function(mod)
return not mod.is_modpack and not mod.is_game_content
end
local conffile = Settings(filename) | ||
|
||
for key,value in pairs(conffile:to_table()) do | ||
if key:sub(1, 9) == "load_mod_" then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do
local mod_name = key:match("^load_mod_(.+)")
if mod_name then
...
end
if key:sub(1, 9) == "load_mod_" then | ||
key = key:sub(10) | ||
local element = nil | ||
for i=1,#retval,1 do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bad style. Just do something like
for i=1,#retval,1 do | |
for _, client_mod in ipairs(client_mods) do |
and give element
a better name (such as found_client_mod
or whatever).
though really i feel you should have client mods indexed in a table by name. then you wouldn't need a linear search here - the code would be cleaner.
local element = nil | ||
for i=1,#retval,1 do | ||
if retval[i].name == key and | ||
not retval[i].is_modpack then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can go on the same line. if you do need continuation lines, indent them by two tabs so they don't blend in with the next line.
break | ||
end | ||
end | ||
if element ~= nil then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if element ~= nil then | |
if element then |
end | ||
end | ||
if element ~= nil then | ||
element.enabled = value ~= "false" and value ~= "nil" and value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
element.enabled = value ~= "false" and value ~= "nil" and value | |
element.enabled = value ~= "false" and value ~= "nil" |
i don't see and value
adding any value, it just creates type confusion: the value
is a string and thus necessarily truthy.
local conffile = Settings(filename) | ||
local mods = conffile:to_table() | ||
|
||
for i = 1, #packages_raw do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for i = 1, #packages_raw do | |
for _, mod in ipairs(packages_raw) do |
but given the name of packages_raw
, wouldn't pkg
be a better name (it looks like this also includes things like modpacks)?
|
||
-- Remove mods that are not present anymore | ||
for key in pairs(mods) do | ||
if key:sub(1, 9) == "load_mod_" then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if key:sub(1, 9) == "load_mod_" then | |
if key:find("^load_mod_") then |
end | ||
end | ||
|
||
if tab_selected_pkg == nil then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if tab_selected_pkg == nil then | |
tab_selected_pkg = tab_selected_pkg or 1 |
then delete the rest of the if
|
||
if selected_pkg ~= nil then | ||
if selected_pkg.type == "mod" then | ||
if selected_pkg.is_clientside then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary if
pyramid. just do if selected_pkg and selected_pkg.type == "mod" and selected_pkg.is_clientside then
(wrap as needed).
return table.concat(fs, "") | ||
end | ||
|
||
-------------------------------------------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-------------------------------------------------------------------------------- |
let's not do these anymore, same below.
return true | ||
end | ||
|
||
if fields.btn_csm_mgr_mp_enable ~= nil or fields.btn_csm_mgr_mp_disable ~= nil then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if fields.btn_csm_mgr_mp_enable ~= nil or fields.btn_csm_mgr_mp_disable ~= nil then | |
if fields.btn_csm_mgr_mp_enable or fields.btn_csm_mgr_mp_disable then |
return true | ||
end | ||
|
||
if fields.btn_csm_mgr_enable_mod ~= nil or fields.btn_csm_mgr_disable_mod ~= nil then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if fields.btn_csm_mgr_enable_mod ~= nil or fields.btn_csm_mgr_disable_mod ~= nil then | |
if fields.btn_csm_mgr_enable_mod or fields.btn_csm_mgr_disable_mod then |
Previously: #10039 Also, the new button's location results in the "Browse online content" button becoming too small for its label - but that doesn't matter much as long as its hidden by default. |
Using this dialog you have the ability to enable or disable client mods without manually editing the file.
Add compact, short information about your PR for easier understanding:
Give players the ability to select csms without manually editing files.
It adds a button to the content tab which opens a dialog with a list of csms and the option to enable or
disable them.
I don't believe so.
Yes, I believe its part of the ui improvements category
Many times in the past I've had people attempting to use my CSMs unable because they can't find the file to
manually enable mods.
To do
This PR is a Ready for Review.
How to test
Simply compile this PR, go to the main menu, open the content tab, and click the Client side mods button