aboutsummaryrefslogtreecommitdiff
path: root/builtin/mainmenu/dlg_config_world.lua
blob: a459f0ff11024eb97ead65889c9ea7801e29f954 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
1/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>

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.
*/

#pragma once

#include <exception>
#include <vector>

#include "irrlichttypes_extrabloated.h"
#include "porting.h"
#include "filesys.h"
#include "mapnode.h"

class TestFailedException : public std::exception {
};

// Runs a unit test and reports results
#define TEST(fxn, ...) {                                                      \
	u64 t1 = porting::getTimeMs();                                            \
	try {                                                                     \
		fxn(__VA_ARGS__);                                                     \
		rawstream << "[PASS] ";                                               \
	} catch (TestFailedException &e) {                                        \
		rawstream << "[FAIL] ";                                               \
		num_tests_failed++;                                                   \
	} catch (std::exception &e) {                                             \
		rawstream << "Caught unhandled exception: " << e.what() << std::endl; \
		rawstream << "[FAIL] ";                                               \
		num_tests_failed++;                                                   \
	}                                                                         \
	num_tests_run++;                                                          \
	u64 tdiff = porting::getTimeMs() - t1;                                    \
	rawstream << #fxn << " - " << tdiff << "ms" << std::endl;                 \
}

// Asserts the specified condition is true, or fails the current unit test
#define UASSERT(x)                                              \
	if (!(x)) {                                                 \
		rawstream << "Test assertion failed: " #x << std::endl  \
			<< "    at " << fs::GetFilenameFromPath(__FILE__)   \
			<< ":" << __LINE__ << std::endl;                    \
		throw TestFailedException();                            \
	}--Minetest
--Copyright (C) 2013 sapier
--
--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.

--------------------------------------------------------------------------------

local function get_formspec(data)

	local mod = data.list:get_list()[data.selected_mod]

	local retval =
		"size[11,6.5,true]" ..
		"label[0.5,-0.25;" .. fgettext("World:") .. "]" ..
		"label[1.75,-0.25;" .. data.worldspec.name .. "]"

	if data.hide_gamemods then
		retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]"
	else
		retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]"
	end

	if data.hide_modpackcontents then
		retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]"
	else
		retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]"
	end

	if mod == nil then
		mod = {name=""}
	end
	
	retval = retval ..
		"label[0,0.45;" .. fgettext("Mod:") .. "]" ..
		"label[0.75,0.45;" .. mod.name .. "]" ..
		"label[0,1;" .. fgettext("Depends:") .. "]" ..
		"textlist[0,1.5;5,4.25;world_config_depends;" ..
		modmgr.get_dependencies(mod.path) .. ";0]" ..
		"button[9.25,6.35;2,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" ..
		"button[7.4,6.35;2,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]"

	if mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then
		if mod.is_modpack then
			local rawlist = data.list:get_raw_list()

			local all_enabled = true
			for j=1,#rawlist,1 do
				if rawlist[j].modpack == mod.name and
					rawlist[j].enabled ~= true then
						all_enabled = false
						break
				end
			end

			if all_enabled == false then
				retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]"
			else
				retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_disable;" .. fgettext("Disable MP") .. "]"
			end
		else
			if mod.enabled then
				retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";true]"
			else
				retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";false]"
			end
		end
	end

	retval = retval ..
		"button[8.5,-0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" ..
		"textlist[5.5,0.5;5.5,5.75;world_config_modlist;"

	retval = retval .. modmgr.render_modlist(data.list)
	retval = retval .. ";" .. data.selected_mod .."]"

	return retval
end

local function enable_mod(this, toset)
	local mod = this.data.list:get_list()[this.data.selected_mod]

	if mod.typ == "game_mod" then
		-- game mods can't be enabled or disabled
	elseif not mod.is_modpack then
		if toset == nil then
			mod.enabled = not mod.enabled
		else
			mod.enabled = toset
		end
	else
		local list = this.data.list:get_raw_list()
		for i=1,#list,1 do
			if list[i].modpack == mod.name then
				if toset == nil then
					toset = not list[i].enabled
				end
				list[i].enabled = toset
			end
		end
	end
end


local function handle_buttons(this, fields)

	if fields["world_config_modlist"] ~= nil then
		local event = core.explode_textlist_event(fields["world_config_modlist"])
		this.data.selected_mod = event.index

		if event.type == "DCL" then
			enable_mod(this)
		end
		
		return true
	end

	if fields["key_enter"] ~= nil then
		enable_mod(this)
		return true
	end

	if fields["cb_mod_enable"] ~= nil then
		local toset = core.is_yes(fields["cb_mod_enable"])
		enable_mod(this,toset)
		return true
	end

	if fields["btn_mp_enable"] ~= nil or
		fields["btn_mp_disable"] then
		local toset = (fields["btn_mp_enable"] ~= nil)
		enable_mod(this,toset)
		return true
	end

	if fields["cb_hide_gamemods"] ~= nil or
		fields["cb_hide_mpcontent"] ~= nil then
		local current = this.data.list:get_filtercriteria()

		if current == nil then
			current = {}
		end

		if core.is_yes(fields["cb_hide_gamemods"]) then
			current.hide_game = true
			this.data.hide_gamemods = true
		else
			current.hide_game = false
			this.data.hide_gamemods = false
		end
		
		if core.is_yes(fields["cb_hide_mpcontent"]) then
			current.hide_modpackcontents = true
			this.data.hide_modpackcontents = true
		else
			current.hide_modpackcontents = false
			this.data.hide_modpackcontents = false
		end

		this.data.list:set_filtercriteria(current)
		return true
	end

	if fields["btn_config_world_save"] then

		local filename = this.data.worldspec.path ..
				DIR_DELIM .. "world.mt"

		local worldfile = Settings(filename)
		local mods = worldfile:to_table()

		local rawlist = this.data.list:get_raw_list()

		local i,mod
		for i,mod in ipairs(rawlist) do
			if not mod.is_modpack and
					mod.typ ~= "game_mod" then
				if mod.enabled then
					worldfile:set("load_mod_"..mod.name, "true")
				else
					worldfile:set("load_mod_"..mod.name, "false")
				end
				mods["load_mod_"..mod.name] = nil
			end
		end

		-- Remove mods that are not present anymore
		for key,value in pairs(mods) do
			if key:sub(1,9) == "load_mod_" then
				worldfile:remove(key)
			end
		end

		if not worldfile:write() then
			core.log("error", "Failed to write world config file")
		end
	
		this:delete()
		return true
	end

	if fields["btn_config_world_cancel"] then
		this:delete()
		return true
	end

	if fields["btn_all_mods"] then
		local list = this.data.list:get_raw_list()

		for i=1,#list,1 do
			if list[i].typ ~= "game_mod" and
				not list[i].is_modpack then
				list[i].enabled = true
			end
		end
		return true
	end

	return false
end

function create_configure_world_dlg(worldidx)

	local dlg = dialog_create("sp_config_world",
					get_formspec,
					handle_buttons,
					nil)

	--TODO read from settings
	dlg.data.hide_gamemods = false
	dlg.data.hide_modpackcontents = false
	dlg.data.selected_mod = 0

	dlg.data.worldspec = core.get_worlds()[worldidx]
	if dlg.data.worldspec == nil then dlg:delete() return nil end

	dlg.data.worldconfig = modmgr.get_worldconfig(dlg.data.worldspec.path)
	
	if dlg.data.worldconfig == nil or dlg.data.worldconfig.id == nil or
			dlg.data.worldconfig.id == "" then

		dlg:delete()
		return nil
	end
	
	dlg.data.list = filterlist.create(
			modmgr.preparemodlist, --refresh
			modmgr.comparemod, --compare
			function(element,uid) --uid match
					if element.name == uid then
						return true
					end
				end,
				function(element,criteria)
					if criteria.hide_game and
						element.typ == "game_mod" then
							return false
					end

					if criteria.hide_modpackcontents and
						element.modpack ~= nil then
							return false
						end
					return true
				end, --filter
				{ worldpath= dlg.data.worldspec.path,
				  gameid = dlg.data.worldspec.gameid }
			)
			
	dlg.data.list:set_filtercriteria(
		{
			hide_game=dlg.data.hide_gamemods,
			hide_modpackcontents= dlg.data.hide_modpackcontents
		})
	dlg.data.list:add_sort_mechanism("alphabetic", sort_mod_list)
	dlg.data.list:set_sortmode("alphabetic")
	
	return dlg
end