Add formspec toolkit and refactor mainmenu to use it

Fix crash on using cursor keys in client menu without selected server
Add support for non fixed size tabviews
This commit is contained in:
sapier 2014-04-18 15:39:15 +02:00
parent 34d872628d
commit c3984569c0
27 changed files with 3518 additions and 2500 deletions

@ -16,6 +16,8 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- TODO improve doc --
-- TODO code cleanup --
-- Generic implementation of a filter/sortable list -- -- Generic implementation of a filter/sortable list --
-- Usage: -- -- Usage: --
-- Filterlist needs to be initialized on creation. To achieve this you need to -- -- Filterlist needs to be initialized on creation. To achieve this you need to --
@ -62,6 +64,20 @@ function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_pa
this.m_processed_list = nil this.m_processed_list = nil
this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param) this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
this.add_sort_mechanism = filterlist.add_sort_mechanism
this.set_filtercriteria = filterlist.set_filtercriteria
this.get_filtercriteria = filterlist.get_filtercriteria
this.set_sortmode = filterlist.set_sortmode
this.get_list = filterlist.get_list
this.get_raw_list = filterlist.get_raw_list
this.get_raw_element = filterlist.get_raw_element
this.get_raw_index = filterlist.get_raw_index
this.get_current_index = filterlist.get_current_index
this.size = filterlist.size
this.uid_exists_raw = filterlist.uid_exists_raw
this.raw_index_by_uid = filterlist.raw_index_by_uid
this.refresh = filterlist.refresh
filterlist.process(this) filterlist.process(this)
return this return this

209
builtin/fstk/buttonbar.lua Normal file

@ -0,0 +1,209 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self 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.
--
--self 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 self program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local function buttonbar_formspec(self)
if self.hidden then
return ""
end
local formspec = string.format("box[%f,%f;%f,%f;%s]",
self.pos.x,self.pos.y ,self.size.x,self.size.y,self.bgcolor)
for i=self.startbutton,#self.buttons,1 do
local btn_name = self.buttons[i].name
local btn_pos = {}
if self.orientation == "horizontal" then
btn_pos.x = self.pos.x + --base pos
(i - self.startbutton) * self.btn_size + --button offset
self.btn_initial_offset
else
btn_pos.x = self.pos.x + (self.btn_size * 0.05)
end
if self.orientation == "vertical" then
btn_pos.y = self.pos.y + --base pos
(i - self.startbutton) * self.btn_size + --button offset
self.btn_initial_offset
else
btn_pos.y = self.pos.y + (self.btn_size * 0.05)
end
if (self.orientation == "vertical" and
(btn_pos.y + self.btn_size <= self.pos.y + self.size.y)) or
(self.orientation == "horizontal" and
(btn_pos.x + self.btn_size <= self.pos.x + self.size.x)) then
local borders="true"
if self.buttons[i].image ~= nil then
borders="false"
end
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;%s]",
btn_pos.x, btn_pos.y, self.btn_size, self.btn_size,
self.buttons[i].image, btn_name, self.buttons[i].caption,
borders)
else
--print("end of displayable buttons: orientation: " .. self.orientation)
--print( "button_end: " .. (btn_pos.y + self.btn_size - (self.btn_size * 0.05)))
--print( "bar_end: " .. (self.pos.x + self.size.x))
break
end
end
if (self.have_move_buttons) then
local btn_dec_pos = {}
btn_dec_pos.x = self.pos.x + (self.btn_size * 0.05)
btn_dec_pos.y = self.pos.y + (self.btn_size * 0.05)
local btn_inc_pos = {}
local btn_size = {}
if self.orientation == "horizontal" then
btn_size.x = 0.5
btn_size.y = self.btn_size
btn_inc_pos.x = self.pos.x + self.size.x - 0.5
btn_inc_pos.y = self.pos.y + (self.btn_size * 0.05)
else
btn_size.x = self.btn_size
btn_size.y = 0.5
btn_inc_pos.x = self.pos.x + (self.btn_size * 0.05)
btn_inc_pos.y = self.pos.y + self.size.y - 0.5
end
local text_dec = "<"
local text_inc = ">"
if self.orientation == "vertical" then
text_dec = "^"
text_inc = "v"
end
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;;btnbar_dec_%s;%s;true;true]",
btn_dec_pos.x, btn_dec_pos.y, btn_size.x, btn_size.y,
self.name, text_dec)
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;;btnbar_dec_%s;%s;true;true]",
btn_inc_pos.x, btn_inc_pos.y, btn_size.x, btn_size.y,
self.name, text_inc)
end
return formspec
end
local function buttonbar_buttonhandler(self, fields)
if fields["btnbar_inc_" .. self.name] ~= nil and
self.startbutton < #self.buttons then
self.startbutton = self.startbutton + 1
return true
end
if fields["btnbar_dec_" .. self.name] ~= nil and self.startbutton > 1 then
self.startbutton = self.startbutton - 1
return true
end
for i=1,#self.buttons,1 do
if fields[self.buttons[i].name] ~= nil then
return self.userbuttonhandler(fields)
end
end
end
local buttonbar_metatable = {
handle_buttons = buttonbar_buttonhandler,
handle_events = function(self, event) end,
get_formspec = buttonbar_formspec,
hide = function(self) self.hidden = true end,
show = function(self) self.hidden = false end,
delete = function(self) ui.delete(self) end,
add_button = function(self, name, caption, image)
if caption == nil then caption = "" end
if image == nil then image = "" end
table.insert(self.buttons,{ name=name, caption=caption, image=image})
if self.orientation == "horizontal" then
if ( (self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
> self.size.x ) then
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
self.have_move_buttons = true
end
else
if ((self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
> self.size.y ) then
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
self.have_move_buttons = true
end
end
end,
set_bgparams = function(self, bgcolor)
if (type(bgcolor) == "string") then
self.bgcolor = bgcolor
end
end,
}
buttonbar_metatable.__index = buttonbar_metatable
function buttonbar_create(name, cbf_buttonhandler, pos, orientation, size)
assert(name ~= nil)
assert(cbf_buttonhandler ~= nil)
assert(orientation == "vertical" or orientation == "horizontal")
assert(pos ~= nil and type(pos) == "table")
assert(size ~= nil and type(size) == "table")
local self = {}
self.name = name
self.type = "addon"
self.bgcolor = "#000000"
self.pos = pos
self.size = size
self.orientation = orientation
self.startbutton = 1
self.have_move_buttons = false
self.hidden = false
if self.orientation == "horizontal" then
self.btn_size = self.size.y
else
self.btn_size = self.size.x
end
if (self.btn_initial_offset == nil) then
self.btn_initial_offset = self.btn_size * 0.05
end
self.userbuttonhandler = cbf_buttonhandler
self.buttons = {}
setmetatable(self,buttonbar_metatable)
ui.add(self)
return self
end

69
builtin/fstk/dialog.lua Normal file

@ -0,0 +1,69 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self 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.
--
--self 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 self program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local function dialog_event_handler(self,event)
if self.user_eventhandler == nil or
self.user_eventhandler(event) == false then
--close dialog on esc
if event == "MenuQuit" then
self:delete()
return true
end
end
end
local dialog_metatable = {
eventhandler = dialog_event_handler,
get_formspec = function(self)
if not self.hidden then return self.formspec(self.data) end
end,
handle_buttons = function(self,fields)
if not self.hidden then return self.buttonhandler(self,fields) end
end,
handle_events = function(self,event)
if not self.hidden then return self.eventhandler(self,event) end
end,
hide = function(self) self.hidden = true end,
show = function(self) self.hidden = false end,
delete = function(self)
if self.parent ~= nil then
self.parent:show()
end
ui.delete(self)
end,
set_parent = function(self,parent) self.parent = parent end
}
dialog_metatable.__index = dialog_metatable
function dialog_create(name,get_formspec,buttonhandler,eventhandler)
local self = {}
self.name = name
self.type = "toplevel"
self.hidden = true
self.data = {}
self.formspec = get_formspec
self.buttonhandler = buttonhandler
self.user_eventhandler = eventhandler
setmetatable(self,dialog_metatable)
ui.add(self)
return self
end

273
builtin/fstk/tabview.lua Normal file

@ -0,0 +1,273 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self 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.
--
--self 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 self program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
-- A tabview implementation --
-- Usage: --
-- tabview.create: returns initialized tabview raw element --
-- element.add(tab): add a tab declaration --
-- element.handle_buttons() --
-- element.handle_events() --
-- element.getFormspec() returns formspec of tabview --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function add_tab(self,tab)
assert(tab.size == nil or (type(tab.size) == table and
tab.size.x ~= nil and tab.size.y ~= nil))
assert(tab.cbf_formspec ~= nil and type(tab.cbf_formspec) == "function")
assert(tab.cbf_button_handler == nil or
type(tab.cbf_button_handler) == "function")
assert(tab.cbf_events == nil or type(tab.cbf_events) == "function")
local newtab = {
name = tab.name,
caption = tab.caption,
button_handler = tab.cbf_button_handler,
event_handler = tab.cbf_events,
get_formspec = tab.cbf_formspec,
tabsize = tab.tabsize,
on_change = tab.on_change,
tabdata = {},
}
table.insert(self.tablist,newtab)
if self.last_tab_index == #self.tablist then
self.current_tab = tab.name
if tab.on_activate ~= nil then
tab.on_activate(nil,tab.name)
end
end
end
--------------------------------------------------------------------------------
local function get_formspec(self)
local formspec = ""
if not self.hidden and (self.parent == nil or not self.parent.hidden) then
if self.parent == nil then
local tsize = self.tablist[self.last_tab_index].tabsize or
{width=self.width, height=self.height}
formspec = formspec ..
string.format("size[%f,%f,%s]",tsize.width,tsize.height,
dump(self.fixed_size))
end
formspec = formspec .. self:tab_header()
formspec = formspec ..
self.tablist[self.last_tab_index].get_formspec(
self,
self.tablist[self.last_tab_index].name,
self.tablist[self.last_tab_index].tabdata,
self.tablist[self.last_tab_index].tabsize
)
end
return formspec
end
--------------------------------------------------------------------------------
local function handle_buttons(self,fields)
if self.hidden then
return false
end
if self:handle_tab_buttons(fields) then
return true
end
if self.glb_btn_handler ~= nil and
self.glb_btn_handler(self,fields) then
return true
end
if self.tablist[self.last_tab_index].button_handler ~= nil then
return
self.tablist[self.last_tab_index].button_handler(
self,
fields,
self.tablist[self.last_tab_index].name,
self.tablist[self.last_tab_index].tabdata
)
end
return false
end
--------------------------------------------------------------------------------
local function handle_events(self,event)
if self.hidden then
return false
end
if self.glb_evt_handler ~= nil and
self.glb_evt_handler(self,event) then
return true
end
if self.tablist[self.last_tab_index].evt_handler ~= nil then
return
self.tablist[self.last_tab_index].evt_handler(
self,
event,
self.tablist[self.last_tab_index].name,
self.tablist[self.last_tab_index].tabdata
)
end
return false
end
--------------------------------------------------------------------------------
local function tab_header(self)
local toadd = ""
for i=1,#self.tablist,1 do
if toadd ~= "" then
toadd = toadd .. ","
end
toadd = toadd .. self.tablist[i].caption
end
return string.format("tabheader[%f,%f;%s;%s;%i;true;false]",
self.header_x, self.header_y, self.name, toadd, self.last_tab_index);
end
--------------------------------------------------------------------------------
local function switch_to_tab(self, index)
--first call on_change for tab to leave
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("LEAVE",
self.current_tab, self.tablist[index].name)
end
--update tabview data
self.last_tab_index = index
local old_tab = self.current_tab
self.current_tab = self.tablist[index].name
if (self.autosave_tab) then
core.setting_set(self.name .. "_LAST",self.current_tab)
end
-- call for tab to enter
if self.tablist[index].on_change ~= nil then
self.tablist[index].on_change("ENTER",
old_tab,self.current_tab)
end
end
--------------------------------------------------------------------------------
local function handle_tab_buttons(self,fields)
--save tab selection to config file
if fields[self.name] then
local index = tonumber(fields[self.name])
switch_to_tab(self, index)
return true
end
return false
end
--------------------------------------------------------------------------------
local function set_tab_by_name(self, name)
for i=1,#self.tablist,1 do
if self.tablist[i].name == name then
switch_to_tab(self, i)
return true
end
end
return false
end
--------------------------------------------------------------------------------
local function hide_tabview(self)
self.hidden=true
--call on_change as we're not gonna show self tab any longer
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("LEAVE",
self.current_tab, nil)
end
end
--------------------------------------------------------------------------------
local function show_tabview(self)
self.hidden=false
-- call for tab to enter
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("ENTER",
nil,self.current_tab)
end
end
local tabview_metatable = {
add = add_tab,
handle_buttons = handle_buttons,
handle_events = handle_events,
get_formspec = get_formspec,
show = show_tabview,
hide = hide_tabview,
delete = function(self) ui.delete(self) end,
set_parent = function(self,parent) self.parent = parent end,
set_autosave_tab =
function(self,value) self.autosave_tab = value end,
set_tab = set_tab_by_name,
set_global_button_handler =
function(self,handler) self.glb_btn_handler = handler end,
set_global_event_handler =
function(self,handler) self.glb_evt_handler = handler end,
set_fixed_size =
function(self,state) self.fixed_size = state end,
tab_header = tab_header,
handle_tab_buttons = handle_tab_buttons
}
tabview_metatable.__index = tabview_metatable
--------------------------------------------------------------------------------
function tabview_create(name, size, tabheaderpos)
local self = {}
self.name = name
self.type = "toplevel"
self.width = size.x
self.height = size.y
self.header_x = tabheaderpos.x
self.header_y = tabheaderpos.y
setmetatable(self, tabview_metatable)
self.fixed_size = true
self.hidden = true
self.current_tab = nil
self.last_tab_index = 1
self.tablist = {}
self.autosave_tab = false
ui.add(self)
return self
end

172
builtin/fstk/ui.lua Normal file

@ -0,0 +1,172 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self 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.
--
--self 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 self program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ui = {}
ui.childlist = {}
ui.default = nil
--------------------------------------------------------------------------------
function ui.add(child)
--TODO check child
ui.childlist[child.name] = child
return child.name
end
--------------------------------------------------------------------------------
function ui.delete(child)
if ui.childlist[child.name] == nil then
return false
end
ui.childlist[child.name] = nil
return true
end
--------------------------------------------------------------------------------
function ui.set_default(name)
ui.default = name
end
--------------------------------------------------------------------------------
function ui.find_by_name(name)
return ui.childlist[name]
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Internal functions not to be called from user
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function ui.update()
local formspec = ""
-- handle errors
if gamedata ~= nil and gamedata.errormessage ~= nil then
formspec = "size[12,3.2]" ..
"textarea[1,1;10,2;;ERROR: " ..
core.formspec_escape(gamedata.errormessage) ..
";]"..
"button[4.5,2.5;3,0.5;btn_error_confirm;" .. fgettext("Ok") .. "]"
else
local active_toplevel_ui_elements = 0
for key,value in pairs(ui.childlist) do
if (value.type == "toplevel") then
local retval = value:get_formspec()
if retval ~= nil and retval ~= "" then
active_toplevel_ui_elements = active_toplevel_ui_elements +1
formspec = formspec .. retval
end
end
end
-- no need to show addons if there ain't a toplevel element
if (active_toplevel_ui_elements > 0) then
for key,value in pairs(ui.childlist) do
if (value.type == "addon") then
local retval = value:get_formspec()
if retval ~= nil and retval ~= "" then
formspec = formspec .. retval
end
end
end
end
if (active_toplevel_ui_elements > 1) then
print("WARNING: ui manager detected more then one active ui element, self most likely isn't intended")
end
if (active_toplevel_ui_elements == 0) then
print("WARNING: not a single toplevel ui element active switching to default")
ui.childlist[ui.default]:show()
formspec = ui.childlist[ui.default]:get_formspec()
end
end
core.update_formspec(formspec)
end
--------------------------------------------------------------------------------
function ui.handle_buttons(fields)
if fields["btn_error_confirm"] then
gamedata.errormessage = nil
update_menu()
return
end
for key,value in pairs(ui.childlist) do
local retval = value:handle_buttons(fields)
if retval then
ui.update()
return
end
end
end
--------------------------------------------------------------------------------
function ui.handle_events(event)
for key,value in pairs(ui.childlist) do
if value.handle_events ~= nil then
local retval = value:handle_events(event)
if retval then
print("event handled by: " .. key)
return retval
end
end
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- initialize callbacks
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
core.button_handler = function(fields)
if fields["btn_error_confirm"] then
gamedata.errormessage = nil
ui.update()
return
end
if ui.handle_buttons(fields) then
ui.update()
end
end
--------------------------------------------------------------------------------
core.event_handler = function(event)
if ui.handle_events(event) then
ui.update()
return
end
if event == "Refresh" then
ui.update()
return
end
end

193
builtin/mainmenu/common.lua Normal file

@ -0,0 +1,193 @@
--Minetest
--Copyright (C) 2014 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.
--------------------------------------------------------------------------------
-- Global menu data
---------------------------------------------------------------------------------
menudata = {}
--------------------------------------------------------------------------------
-- Menu helper functions
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function render_favorite(spec,render_details)
local text = ""
if spec.name ~= nil then
text = text .. core.formspec_escape(spec.name:trim())
-- if spec.description ~= nil and
-- core.formspec_escape(spec.description):trim() ~= "" then
-- text = text .. " (" .. core.formspec_escape(spec.description) .. ")"
-- end
else
if spec.address ~= nil then
text = text .. spec.address:trim()
if spec.port ~= nil then
text = text .. ":" .. spec.port
end
end
end
if not render_details then
return text
end
local details = ""
if spec.password == true then
details = details .. "*"
else
details = details .. "_"
end
if spec.creative then
details = details .. "C"
else
details = details .. "_"
end
if spec.damage then
details = details .. "D"
else
details = details .. "_"
end
if spec.pvp then
details = details .. "P"
else
details = details .. "_"
end
details = details .. " "
local playercount = ""
if spec.clients ~= nil and
spec.clients_max ~= nil then
playercount = string.format("%03d",spec.clients) .. "/" ..
string.format("%03d",spec.clients_max) .. " "
end
return playercount .. core.formspec_escape(details) .. text
end
--------------------------------------------------------------------------------
os.tempfolder = function()
if core.setting_get("TMPFolder") then
return core.setting_get("TMPFolder") .. DIR_DELIM .. "MT_" .. math.random(0,10000)
end
local filetocheck = os.tmpname()
os.remove(filetocheck)
local randname = "MTTempModFolder_" .. math.random(0,10000)
if DIR_DELIM == "\\" then
local tempfolder = os.getenv("TEMP")
return tempfolder .. filetocheck
else
local backstring = filetocheck:reverse()
return filetocheck:sub(0,filetocheck:len()-backstring:find(DIR_DELIM)+1) ..randname
end
end
--------------------------------------------------------------------------------
function menu_render_worldlist()
local retval = ""
local current_worldlist = menudata.worldlist:get_list()
for i,v in ipairs(current_worldlist) do
if retval ~= "" then
retval = retval ..","
end
retval = retval .. core.formspec_escape(v.name) ..
" \\[" .. core.formspec_escape(v.gameid) .. "\\]"
end
return retval
end
--------------------------------------------------------------------------------
function menu_handle_key_up_down(fields,textlist,settingname)
if fields["key_up"] then
local oldidx = core.get_textlist_index(textlist)
if oldidx ~= nil and oldidx > 1 then
local newidx = oldidx -1
core.setting_set(settingname,
menudata.worldlist:get_raw_index(newidx))
end
return true
end
if fields["key_down"] then
local oldidx = core.get_textlist_index(textlist)
if oldidx ~= nil and oldidx < menudata.worldlist:size() then
local newidx = oldidx + 1
core.setting_set(settingname,
menudata.worldlist:get_raw_index(newidx))
end
return true
end
return false
end
--------------------------------------------------------------------------------
function asyncOnlineFavourites()
menudata.favorites = {}
core.handle_async(
function(param)
return core.get_favorites("online")
end,
nil,
function(result)
menudata.favorites = result
core.event_handler("Refresh")
end
)
end
--------------------------------------------------------------------------------
function text2textlist(xpos,ypos,width,height,tl_name,textlen,text,transparency)
local textlines = core.splittext(text,textlen)
local retval = "textlist[" .. xpos .. "," .. ypos .. ";"
.. width .. "," .. height .. ";"
.. tl_name .. ";"
for i=1, #textlines, 1 do
textlines[i] = textlines[i]:gsub("\r","")
retval = retval .. core.formspec_escape(textlines[i]) .. ","
end
retval = retval .. ";0;"
if transparency then
retval = retval .. "true"
end
retval = retval .. "]"
return retval
end

@ -0,0 +1,290 @@
--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

@ -0,0 +1,132 @@
--Minetest
--Copyright (C) 2014 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 create_world_formspec(dialogdata)
local mapgens = {"v6", "v7", "indev", "singlenode", "math"}
local current_seed = core.setting_get("fixed_map_seed") or ""
local current_mg = core.setting_get("mg_name")
local mglist = ""
local selindex = 1
local i = 1
for k,v in pairs(mapgens) do
if current_mg == v then
selindex = i
end
i = i + 1
mglist = mglist .. v .. ","
end
mglist = mglist:sub(1, -2)
local gameid = core.setting_get("menu_last_game")
local game, gameidx = nil , 0
if gameid ~= nil then
game, gameidx = gamemgr.find_by_gameid(gameid)
if gameidx == nil then
gameidx = 0
end
end
local retval =
"size[12,6,true]" ..
"label[2,0;" .. fgettext("World name") .. "]"..
"field[4.5,0.4;6,0.5;te_world_name;;]" ..
"label[2,1;" .. fgettext("Seed") .. "]"..
"field[4.5,1.4;6,0.5;te_seed;;".. current_seed .. "]" ..
"label[2,2;" .. fgettext("Mapgen") .. "]"..
"dropdown[4.2,2;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" ..
"label[2,3;" .. fgettext("Game") .. "]"..
"textlist[4.2,3;5.8,2.3;games;" .. gamemgr.gamelist() ..
";" .. gameidx .. ";true]" ..
"button[5,5.5;2.6,0.5;world_create_confirm;" .. fgettext("Create") .. "]" ..
"button[7.5,5.5;2.8,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
return retval
end
local function create_world_buttonhandler(this, fields)
if fields["world_create_confirm"] or
fields["key_enter"] then
local worldname = fields["te_world_name"]
local gameindex = core.get_textlist_index("games")
if gameindex ~= nil and
worldname ~= "" then
local message = nil
if not menudata.worldlist:uid_exists_raw(worldname) then
core.setting_set("mg_name",fields["dd_mapgen"])
message = core.create_world(worldname,gameindex)
else
message = fgettext("A world named \"$1\" already exists", worldname)
end
core.setting_set("fixed_map_seed", fields["te_seed"])
if message ~= nil then
gamedata.errormessage = message
else
core.setting_set("menu_last_game",gamemgr.games[gameindex].id)
if this.data.update_worldlist_filter then
menudata.worldlist:set_filtercriteria(gamemgr.games[gameindex].id)
mm_texture.update("singleplayer", gamemgr.games[gameindex].id)
end
menudata.worldlist:refresh()
core.setting_set("mainmenu_last_selected_world",
menudata.worldlist:raw_index_by_uid(worldname))
end
else
gamedata.errormessage =
fgettext("No worldname given or no game selected")
end
this:delete()
return true
end
if fields["games"] then
return true
end
if fields["world_create_cancel"] then
this:delete()
return true
end
return false
end
function create_create_world_dlg(update_worldlistfilter)
local retval = dialog_create("sp_create_world",
create_world_formspec,
create_world_buttonhandler,
nil)
retval.update_worldlist_filter = update_worldlistfilter
return retval
end

@ -0,0 +1,68 @@
--Minetest
--Copyright (C) 2014 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 delete_mod_formspec(dialogdata)
dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected]
local retval =
"size[12.4,5,true]" ..
"field[1.75,1;10,3;;" .. fgettext("Are you sure you want to delete \"$1\"?", dialogdata.mod.name) .. ";]"..
"button[4,4.2;1,0.5;dlg_delete_mod_confirm;" .. fgettext("Yes") .. "]" ..
"button[6.5,4.2;3,0.5;dlg_delete_mod_cancel;" .. fgettext("No of course not!") .. "]"
return retval
end
--------------------------------------------------------------------------------
local function delete_mod_buttonhandler(this, fields)
if fields["dlg_delete_mod_confirm"] ~= nil then
if this.data.mod.path ~= nil and
this.data.mod.path ~= "" and
this.data.mod.path ~= core.get_modpath() then
if not core.delete_dir(this.data.mod.path) then
gamedata.errormessage = fgettext("Modmgr: failed to delete \"$1\"", this.data.mod.path)
end
modmgr.refresh_globals()
else
gamedata.errormessage = fgettext("Modmgr: invalid modpath \"$1\"", this.data.mod.path)
end
this:delete()
return true
end
if fields["dlg_delete_mod_cancel"] then
this:delete()
return true
end
return false
end
--------------------------------------------------------------------------------
function create_delete_mod_dlg(selected_index)
local retval = dialog_create("dlg_delete_mod",
delete_mod_formspec,
delete_mod_buttonhandler,
nil)
retval.data.selected = selected_index
return retval
end

@ -0,0 +1,64 @@
--Minetest
--Copyright (C) 2014 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 create_world_formspec(dialogdata)
local retval =
"size[12,6,true]" ..
"label[2,2;" ..
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]"..
"button[3.5,4.2;2.6,0.5;world_delete_confirm;" .. fgettext("Yes").. "]" ..
"button[6,4.2;2.8,0.5;world_delete_cancel;" .. fgettext("No") .. "]"
return retval
end
local function create_world_buttonhandler(this, fields)
if fields["world_delete_confirm"] then
if this.data.delete_index > 0 and
this.data.delete_index <= #menudata.worldlist:get_raw_list() then
core.delete_world(this.data.delete_index)
menudata.worldlist:refresh()
end
this:delete()
return true
end
if fields["world_delete_cancel"] then
this:delete()
return true
end
return false
end
function create_delete_world_dlg(name_to_del,index_to_del)
assert(name_to_del ~= nil and type(name_to_del) == "string" and name_to_del ~= "")
assert(index_to_del ~= nil and type(index_to_del) == "number")
local retval = dialog_create("sp_create_world",
create_world_formspec,
create_world_buttonhandler,
nil)
retval.data.delete_name = name_to_del
retval.data.delete_index = index_to_del
return retval
end

@ -0,0 +1,69 @@
--Minetest
--Copyright (C) 2014 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 rename_modpack_formspec(dialogdata)
dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected]
local retval =
"size[12.4,5,true]" ..
"label[1.75,1;".. fgettext("Rename Modpack:") .. "]"..
"field[4.5,1.4;6,0.5;te_modpack_name;;" ..
dialogdata.mod.name ..
"]" ..
"button[5,4.2;2.6,0.5;dlg_rename_modpack_confirm;"..
fgettext("Accept") .. "]" ..
"button[7.5,4.2;2.8,0.5;dlg_rename_modpack_cancel;"..
fgettext("Cancel") .. "]"
return retval
end
--------------------------------------------------------------------------------
local function rename_modpack_buttonhandler(this, fields)
if fields["dlg_rename_modpack_confirm"] ~= nil then
local oldpath = core.get_modpath() .. DIR_DELIM .. this.data.mod.name
local targetpath = core.get_modpath() .. DIR_DELIM .. fields["te_modpack_name"]
core.copy_dir(oldpath,targetpath,false)
modmgr.refresh_globals()
modmgr.selected_mod = modmgr.global_mods:get_current_index(
modmgr.global_mods:raw_index_by_uid(fields["te_modpack_name"]))
this:delete()
return true
end
if fields["dlg_rename_modpack_cancel"] then
this:delete()
return true
end
return false
end
--------------------------------------------------------------------------------
function create_rename_modpack_dlg(selected_index)
local retval = dialog_create("dlg_delete_mod",
rename_modpack_formspec,
rename_modpack_buttonhandler,
nil)
retval.data.selected = selected_index
return retval
end

@ -17,143 +17,6 @@
gamemgr = {} gamemgr = {}
--------------------------------------------------------------------------------
function gamemgr.dialog_new_game()
local retval =
"label[2,2;" .. fgettext("Game Name") .. "]"..
"field[4.5,2.4;6,0.5;te_game_name;;]" ..
"button[5,4.2;2.6,0.5;new_game_confirm;" .. fgettext("Create") .. "]" ..
"button[7.5,4.2;2.8,0.5;new_game_cancel;" .. fgettext("Cancel") .. "]"
return retval
end
--------------------------------------------------------------------------------
function gamemgr.handle_games_buttons(fields)
if fields["gamelist"] ~= nil then
local event = engine.explode_textlist_event(fields["gamelist"])
gamemgr.selected_game = event.index
end
if fields["btn_game_mgr_edit_game"] ~= nil then
return {
is_dialog = true,
show_buttons = false,
current_tab = "dialog_edit_game"
}
end
if fields["btn_game_mgr_new_game"] ~= nil then
return {
is_dialog = true,
show_buttons = false,
current_tab = "dialog_new_game"
}
end
return nil
end
--------------------------------------------------------------------------------
function gamemgr.handle_new_game_buttons(fields)
if fields["new_game_confirm"] and
fields["te_game_name"] ~= nil and
fields["te_game_name"] ~= "" then
local gamepath = engine.get_gamepath()
if gamepath ~= nil and
gamepath ~= "" then
local gamefolder = cleanup_path(fields["te_game_name"])
--TODO check for already existing first
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder)
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "mods")
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "menu")
local gameconf =
io.open(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "game.conf","w")
if gameconf then
gameconf:write("name = " .. fields["te_game_name"])
gameconf:close()
end
end
end
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
--------------------------------------------------------------------------------
function gamemgr.handle_edit_game_buttons(fields)
local current_game = gamemgr.get_game(gamemgr.selected_game)
if fields["btn_close_edit_game"] ~= nil or
current_game == nil then
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
if fields["btn_remove_mod_from_game"] ~= nil then
gamemgr.delete_mod(current_game,engine.get_textlist_index("mods_current"))
end
if fields["btn_add_mod_to_game"] ~= nil then
local modindex = engine.get_textlist_index("mods_available")
local mod = modmgr.get_global_mod(modindex)
if mod ~= nil then
local sourcepath = mod.path
if not gamemgr.add_mod(current_game,sourcepath) then
gamedata.errormessage =
fgettext("Gamemgr: Unable to copy mod \"$1\" to game \"$2\"", mod.name, current_game.id)
end
end
end
return nil
end
--------------------------------------------------------------------------------
function gamemgr.add_mod(gamespec,sourcepath)
if gamespec.gamemods_path ~= nil and
gamespec.gamemods_path ~= "" then
local modname = get_last_folder(sourcepath)
return engine.copy_dir(sourcepath,gamespec.gamemods_path .. DIR_DELIM .. modname);
end
return false
end
--------------------------------------------------------------------------------
function gamemgr.delete_mod(gamespec,modindex)
if gamespec.gamemods_path ~= nil and
gamespec.gamemods_path ~= "" then
local game_mods = {}
get_mods(gamespec.gamemods_path,game_mods)
if modindex > 0 and
#game_mods >= modindex then
if game_mods[modindex].path:sub(0,gamespec.gamemods_path:len())
== gamespec.gamemods_path then
engine.delete_dir(game_mods[modindex].path)
end
end
end
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function gamemgr.find_by_gameid(gameid) function gamemgr.find_by_gameid(gameid)
for i=1,#gamemgr.games,1 do for i=1,#gamemgr.games,1 do
@ -187,113 +50,6 @@ function gamemgr.get_game_modlist(gamespec)
return retval return retval
end end
--------------------------------------------------------------------------------
function gamemgr.gettab(name)
local retval = ""
if name == "dialog_edit_game" then
retval = retval .. gamemgr.dialog_edit_game()
end
if name == "dialog_new_game" then
retval = retval .. gamemgr.dialog_new_game()
end
if name == "game_mgr" then
retval = retval .. gamemgr.tab()
end
return retval
end
--------------------------------------------------------------------------------
function gamemgr.tab()
if gamemgr.selected_game == nil then
gamemgr.selected_game = 1
end
local retval =
"vertlabel[0,-0.25;" .. fgettext("GAMES") .. "]" ..
"label[1,-0.25;" .. fgettext("Games") .. ":]" ..
"textlist[1,0.25;4.5,4.4;gamelist;" ..
gamemgr.gamelist() ..
";" .. gamemgr.selected_game .. "]"
local current_game = gamemgr.get_game(gamemgr.selected_game)
if current_game ~= nil then
if current_game.menuicon_path ~= nil and
current_game.menuicon_path ~= "" then
retval = retval ..
"image[5.8,-0.25;2,2;" ..
engine.formspec_escape(current_game.menuicon_path) .. "]"
end
retval = retval ..
"field[8,-0.25;6,2;;" .. current_game.name .. ";]"..
"label[6,1.4;" .. fgettext("Mods:") .."]" ..
"button[9.7,1.5;2,0.2;btn_game_mgr_edit_game;" .. fgettext("edit game") .. "]" ..
"textlist[6,2;5.5,3.3;game_mgr_modlist;"
.. gamemgr.get_game_modlist(current_game) ..";0]" ..
"button[1,4.75;3.2,0.5;btn_game_mgr_new_game;" .. fgettext("new game") .. "]"
end
return retval
end
--------------------------------------------------------------------------------
function gamemgr.dialog_edit_game()
local current_game = gamemgr.get_game(gamemgr.selected_game)
if current_game ~= nil then
local retval =
"vertlabel[0,-0.25;" .. fgettext("EDIT GAME") .."]" ..
"label[0,-0.25;" .. current_game.name .. "]" ..
"button[11.55,-0.2;0.75,0.5;btn_close_edit_game;x]"
if current_game.menuicon_path ~= nil and
current_game.menuicon_path ~= "" then
retval = retval ..
"image[5.25,0;2,2;" ..
engine.formspec_escape(current_game.menuicon_path) .. "]"
end
retval = retval ..
"textlist[0.5,0.5;4.5,4.3;mods_current;"
.. gamemgr.get_game_modlist(current_game) ..";0]"
retval = retval ..
"textlist[7,0.5;4.5,4.3;mods_available;"
.. modmgr.render_modlist() .. ";0]"
retval = retval ..
"button[0.55,4.95;4.7,0.5;btn_remove_mod_from_game;" .. fgettext("Remove selected mod") .."]"
retval = retval ..
"button[7.05,4.95;4.7,0.5;btn_add_mod_to_game;" .. fgettext("<<-- Add mod") .."]"
return retval
end
end
--------------------------------------------------------------------------------
function gamemgr.handle_buttons(tab,fields)
local retval = nil
if tab == "dialog_edit_game" then
retval = gamemgr.handle_edit_game_buttons(fields)
end
if tab == "dialog_new_game" then
retval = gamemgr.handle_new_game_buttons(fields)
end
if tab == "game_mgr" then
retval = gamemgr.handle_games_buttons(fields)
end
return retval
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function gamemgr.get_game(index) function gamemgr.get_game(index)
if index > 0 and index <= #gamemgr.games then if index > 0 and index <= #gamemgr.games then
@ -305,7 +61,7 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function gamemgr.update_gamelist() function gamemgr.update_gamelist()
gamemgr.games = engine.get_games() gamemgr.games = core.get_games()
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -320,3 +76,8 @@ function gamemgr.gamelist()
end end
return retval return retval
end end
--------------------------------------------------------------------------------
-- read initial data
--------------------------------------------------------------------------------
gamemgr.update_gamelist()

File diff suppressed because it is too large Load Diff

@ -1,80 +0,0 @@
--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.
menubar = {}
--------------------------------------------------------------------------------
function menubar.handle_buttons(fields)
for i=1,#menubar.buttons,1 do
if fields[menubar.buttons[i].btn_name] ~= nil then
menu.last_game = menubar.buttons[i].index
engine.setting_set("main_menu_last_game_idx",menu.last_game)
menu.update_gametype()
end
end
end
--------------------------------------------------------------------------------
function menubar.refresh()
menubar.formspec = "box[-0.3,5.625;12.4,1.2;#000000]" ..
"box[-0.3,5.6;12.4,0.05;#FFFFFF]"
menubar.buttons = {}
local button_base = -0.08
local maxbuttons = #gamemgr.games
if maxbuttons > 11 then
maxbuttons = 11
end
for i=1,maxbuttons,1 do
local btn_name = "menubar_btn_" .. gamemgr.games[i].id
local buttonpos = button_base + (i-1) * 1.1
if gamemgr.games[i].menuicon_path ~= nil and
gamemgr.games[i].menuicon_path ~= "" then
menubar.formspec = menubar.formspec ..
"image_button[" .. buttonpos .. ",5.72;1.165,1.175;" ..
engine.formspec_escape(gamemgr.games[i].menuicon_path) .. ";" ..
btn_name .. ";;true;false]"
else
local part1 = gamemgr.games[i].id:sub(1,5)
local part2 = gamemgr.games[i].id:sub(6,10)
local part3 = gamemgr.games[i].id:sub(11)
local text = part1 .. "\n" .. part2
if part3 ~= nil and
part3 ~= "" then
text = text .. "\n" .. part3
end
menubar.formspec = menubar.formspec ..
"image_button[" .. buttonpos .. ",5.72;1.165,1.175;;" ..btn_name ..
";" .. text .. ";true;true]"
end
local toadd = {
btn_name = btn_name,
index = i,
}
table.insert(menubar.buttons,toadd)
end
end

@ -18,7 +18,7 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function get_mods(path,retval,modpack) function get_mods(path,retval,modpack)
local mods = engine.get_dirlist(path,true) local mods = core.get_dirlist(path,true)
for i=1,#mods,1 do for i=1,#mods,1 do
local toadd = {} local toadd = {}
local modpackfile = nil local modpackfile = nil
@ -55,8 +55,8 @@ function modmgr.extract(modfile)
if tempfolder ~= nil and if tempfolder ~= nil and
tempfolder ~= "" then tempfolder ~= "" then
engine.create_dir(tempfolder) core.create_dir(tempfolder)
if engine.extract_zip(modfile.name,tempfolder) then if core.extract_zip(modfile.name,tempfolder) then
return tempfolder return tempfolder
end end
end end
@ -92,7 +92,7 @@ function modmgr.getbasefolder(temppath)
} }
end end
local subdirs = engine.get_dirlist(temppath,true) local subdirs = core.get_dirlist(temppath,true)
--only single mod or modpack allowed --only single mod or modpack allowed
if #subdirs ~= 1 then if #subdirs ~= 1 then
@ -193,9 +193,16 @@ function modmgr.identify_modname(modpath,filename)
while line~= nil do while line~= nil do
local modname = nil local modname = nil
if line:find("register_tool") or if line:find("minetest.register_tool") then
line:find("register_craftitem") or modname = modmgr.parse_register_line(line)
line:find("register_node") then end
if line:find("minetest.register_craftitem") then
modname = modmgr.parse_register_line(line)
end
if line:find("minetest.register_node") then
modname = modmgr.parse_register_line(line) modname = modmgr.parse_register_line(line)
end end
@ -215,139 +222,6 @@ function modmgr.identify_modname(modpath,filename)
return nil return nil
end end
--------------------------------------------------------------------------------
function modmgr.tab()
if modmgr.global_mods == nil then
modmgr.refresh_globals()
end
if modmgr.selected_mod == nil then
modmgr.selected_mod = 1
end
local retval =
"vertlabel[0,-0.25;".. fgettext("MODS") .. "]" ..
"label[0.8,-0.25;".. fgettext("Installed Mods:") .. "]" ..
"textlist[0.75,0.25;4.5,4;modlist;" ..
modmgr.render_modlist(modmgr.global_mods) ..
";" .. modmgr.selected_mod .. "]"
retval = retval ..
"label[0.8,4.2;" .. fgettext("Add mod:") .. "]" ..
-- TODO Disabled due to upcoming release 0.4.8 and irrlicht messing up localization
-- "button[0.75,4.85;1.8,0.5;btn_mod_mgr_install_local;".. fgettext("Local install") .. "]" ..
"button[2.45,4.85;3.05,0.5;btn_mod_mgr_download;".. fgettext("Online mod repository") .. "]"
local selected_mod = nil
if filterlist.size(modmgr.global_mods) >= modmgr.selected_mod then
selected_mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
end
if selected_mod ~= nil then
local modscreenshot = nil
--check for screenshot beeing available
local screenshotfilename = selected_mod.path .. DIR_DELIM .. "screenshot.png"
local error = nil
screenshotfile,error = io.open(screenshotfilename,"r")
if error == nil then
screenshotfile:close()
modscreenshot = screenshotfilename
end
if modscreenshot == nil then
modscreenshot = modstore.basetexturedir .. "no_screenshot.png"
end
retval = retval
.. "image[5.5,0;3,2;" .. engine.formspec_escape(modscreenshot) .. "]"
.. "label[8.25,0.6;" .. selected_mod.name .. "]"
local descriptionlines = nil
error = nil
local descriptionfilename = selected_mod.path .. "description.txt"
descriptionfile,error = io.open(descriptionfilename,"r")
if error == nil then
descriptiontext = descriptionfile:read("*all")
descriptionlines = engine.splittext(descriptiontext,42)
descriptionfile:close()
else
descriptionlines = {}
table.insert(descriptionlines,fgettext("No mod description available"))
end
retval = retval ..
"label[5.5,1.7;".. fgettext("Mod information:") .. "]" ..
"textlist[5.5,2.2;6.2,2.4;description;"
for i=1,#descriptionlines,1 do
retval = retval .. engine.formspec_escape(descriptionlines[i]) .. ","
end
if selected_mod.is_modpack then
retval = retval .. ";0]" ..
"button[10,4.85;2,0.5;btn_mod_mgr_rename_modpack;" ..
fgettext("Rename") .. "]"
retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;"
.. fgettext("Uninstall selected modpack") .. "]"
else
--show dependencies
retval = retval .. ",Depends:,"
toadd = modmgr.get_dependencies(selected_mod.path)
retval = retval .. toadd .. ";0]"
retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;"
.. fgettext("Uninstall selected mod") .. "]"
end
end
return retval
end
--------------------------------------------------------------------------------
function modmgr.dialog_rename_modpack()
local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
local retval =
"label[1.75,1;".. fgettext("Rename Modpack:") .. "]"..
"field[4.5,1.4;6,0.5;te_modpack_name;;" ..
mod.name ..
"]" ..
"button[5,4.2;2.6,0.5;dlg_rename_modpack_confirm;"..
fgettext("Accept") .. "]" ..
"button[7.5,4.2;2.8,0.5;dlg_rename_modpack_cancel;"..
fgettext("Cancel") .. "]"
return retval
end
--------------------------------------------------------------------------------
function modmgr.precheck()
if modmgr.world_config_selected_world == nil then
modmgr.world_config_selected_world = 1
end
if modmgr.world_config_selected_mod == nil then
modmgr.world_config_selected_mod = 1
end
if modmgr.hide_gamemods == nil then
modmgr.hide_gamemods = true
end
if modmgr.hide_modpackcontents == nil then
modmgr.hide_modpackcontents = true
end
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function modmgr.render_modlist(render_list) function modmgr.render_modlist(render_list)
local retval = "" local retval = ""
@ -359,7 +233,7 @@ function modmgr.render_modlist(render_list)
render_list = modmgr.global_mods render_list = modmgr.global_mods
end end
local list = filterlist.get_list(render_list) local list = render_list:get_list()
local last_modpack = nil local last_modpack = nil
for i,v in ipairs(list) do for i,v in ipairs(list) do
@ -370,7 +244,7 @@ function modmgr.render_modlist(render_list)
local color = "" local color = ""
if v.is_modpack then if v.is_modpack then
local rawlist = filterlist.get_raw_list(render_list) local rawlist = render_list:get_raw_list()
local all_enabled = true local all_enabled = true
for j=1,#rawlist,1 do for j=1,#rawlist,1 do
@ -406,104 +280,6 @@ function modmgr.render_modlist(render_list)
return retval return retval
end end
--------------------------------------------------------------------------------
function modmgr.dialog_configure_world()
modmgr.precheck()
local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
local mod = filterlist.get_list(modmgr.modlist)[modmgr.world_config_selected_mod]
local retval =
"size[11,6.5,true]" ..
"label[0.5,-0.25;" .. fgettext("World:") .. "]" ..
"label[1.75,-0.25;" .. worldspec.name .. "]"
if modmgr.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 modmgr.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 = filterlist.get_raw_list(modmgr.modlist)
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(modmgr.modlist)
retval = retval .. ";" .. modmgr.world_config_selected_mod .."]"
return retval
end
--------------------------------------------------------------------------------
function modmgr.handle_buttons(tab,fields)
local retval = nil
if tab == "mod_mgr" then
retval = modmgr.handle_modmgr_buttons(fields)
end
if tab == "dialog_rename_modpack" then
retval = modmgr.handle_rename_modpack_buttons(fields)
end
if tab == "dialog_delete_mod" then
retval = modmgr.handle_delete_mod_buttons(fields)
end
if tab == "dialog_configure_world" then
retval = modmgr.handle_configure_world_buttons(fields)
end
return retval
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function modmgr.get_dependencies(modfolder) function modmgr.get_dependencies(modfolder)
local toadd = "" local toadd = ""
@ -529,7 +305,6 @@ function modmgr.get_dependencies(modfolder)
return toadd return toadd
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function modmgr.get_worldconfig(worldpath) function modmgr.get_worldconfig(worldpath)
local filename = worldpath .. local filename = worldpath ..
@ -545,7 +320,7 @@ function modmgr.get_worldconfig(worldpath)
if key == "gameid" then if key == "gameid" then
worldconfig.id = value worldconfig.id = value
else else
worldconfig.global_mods[key] = engine.is_yes(value) worldconfig.global_mods[key] = core.is_yes(value)
end end
end end
@ -555,52 +330,6 @@ function modmgr.get_worldconfig(worldpath)
return worldconfig return worldconfig
end end
--------------------------------------------------------------------------------
function modmgr.handle_modmgr_buttons(fields)
local retval = {
tab = nil,
is_dialog = nil,
show_buttons = nil,
}
if fields["modlist"] ~= nil then
local event = engine.explode_textlist_event(fields["modlist"])
modmgr.selected_mod = event.index
end
if fields["btn_mod_mgr_install_local"] ~= nil then
engine.show_file_open_dialog("mod_mgt_open_dlg",fgettext("Select Mod File:"))
end
if fields["btn_mod_mgr_download"] ~= nil then
modstore.update_modlist()
retval.current_tab = "dialog_modstore_unsorted"
retval.is_dialog = true
retval.show_buttons = false
return retval
end
if fields["btn_mod_mgr_rename_modpack"] ~= nil then
retval.current_tab = "dialog_rename_modpack"
retval.is_dialog = true
retval.show_buttons = false
return retval
end
if fields["btn_mod_mgr_delete_mod"] ~= nil then
retval.current_tab = "dialog_delete_mod"
retval.is_dialog = true
retval.show_buttons = false
return retval
end
if fields["mod_mgt_open_dlg_accepted"] ~= nil and
fields["mod_mgt_open_dlg_accepted"] ~= "" then
modmgr.installmod(fields["mod_mgt_open_dlg_accepted"],nil)
end
return nil;
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function modmgr.installmod(modfilename,basename) function modmgr.installmod(modfilename,basename)
@ -613,7 +342,6 @@ function modmgr.installmod(modfilename,basename)
return return
end end
local basefolder = modmgr.getbasefolder(modpath) local basefolder = modmgr.getbasefolder(modpath)
if basefolder.type == "modpack" then if basefolder.type == "modpack" then
@ -628,8 +356,8 @@ function modmgr.installmod(modfilename,basename)
end end
if clean_path ~= nil then if clean_path ~= nil then
local targetpath = engine.get_modpath() .. DIR_DELIM .. clean_path local targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
if not engine.copy_dir(basefolder.path,targetpath) then if not core.copy_dir(basefolder.path,targetpath) then
gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath) gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath)
end end
else else
@ -650,234 +378,19 @@ function modmgr.installmod(modfilename,basename)
end end
if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then
local targetpath = engine.get_modpath() .. DIR_DELIM .. targetfolder local targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
engine.copy_dir(basefolder.path,targetpath) core.copy_dir(basefolder.path,targetpath)
else else
gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename) gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename)
end end
end end
engine.delete_dir(modpath) core.delete_dir(modpath)
modmgr.refresh_globals() modmgr.refresh_globals()
end end
--------------------------------------------------------------------------------
function modmgr.handle_rename_modpack_buttons(fields)
if fields["dlg_rename_modpack_confirm"] ~= nil then
local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
local oldpath = engine.get_modpath() .. DIR_DELIM .. mod.name
local targetpath = engine.get_modpath() .. DIR_DELIM .. fields["te_modpack_name"]
engine.copy_dir(oldpath,targetpath,false)
modmgr.refresh_globals()
modmgr.selected_mod = filterlist.get_current_index(modmgr.global_mods,
filterlist.raw_index_by_uid(modmgr.global_mods, fields["te_modpack_name"]))
end
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
--------------------------------------------------------------------------------
function modmgr.handle_configure_world_buttons(fields)
if fields["world_config_modlist"] ~= nil then
local event = engine.explode_textlist_event(fields["world_config_modlist"])
modmgr.world_config_selected_mod = event.index
if event.type == "DCL" then
modmgr.world_config_enable_mod(nil)
end
end
if fields["key_enter"] ~= nil then
modmgr.world_config_enable_mod(nil)
end
if fields["cb_mod_enable"] ~= nil then
local toset = engine.is_yes(fields["cb_mod_enable"])
modmgr.world_config_enable_mod(toset)
end
if fields["btn_mp_enable"] ~= nil or
fields["btn_mp_disable"] then
local toset = (fields["btn_mp_enable"] ~= nil)
modmgr.world_config_enable_mod(toset)
end
if fields["cb_hide_gamemods"] ~= nil then
local current = filterlist.get_filtercriteria(modmgr.modlist)
if current == nil then
current = {}
end
if engine.is_yes(fields["cb_hide_gamemods"]) then
current.hide_game = true
modmgr.hide_gamemods = true
else
current.hide_game = false
modmgr.hide_gamemods = false
end
filterlist.set_filtercriteria(modmgr.modlist,current)
end
if fields["cb_hide_mpcontent"] ~= nil then
local current = filterlist.get_filtercriteria(modmgr.modlist)
if current == nil then
current = {}
end
if engine.is_yes(fields["cb_hide_mpcontent"]) then
current.hide_modpackcontents = true
modmgr.hide_modpackcontents = true
else
current.hide_modpackcontents = false
modmgr.hide_modpackcontents = false
end
filterlist.set_filtercriteria(modmgr.modlist,current)
end
if fields["btn_config_world_save"] then
local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
local filename = worldspec.path ..
DIR_DELIM .. "world.mt"
local worldfile = Settings(filename)
local mods = worldfile:to_table()
local rawlist = filterlist.get_raw_list(modmgr.modlist)
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
engine.log("error", "Failed to write world config file")
end
modmgr.modlist = nil
modmgr.worldconfig = nil
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
if fields["btn_config_world_cancel"] then
modmgr.worldconfig = nil
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
if fields["btn_all_mods"] then
local list = filterlist.get_raw_list(modmgr.modlist)
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
end
return nil
end
--------------------------------------------------------------------------------
function modmgr.world_config_enable_mod(toset)
local mod = filterlist.get_list(modmgr.modlist)
[engine.get_textlist_index("world_config_modlist")]
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 = filterlist.get_raw_list(modmgr.modlist)
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
--------------------------------------------------------------------------------
function modmgr.handle_delete_mod_buttons(fields)
local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
if fields["dlg_delete_mod_confirm"] ~= nil then
if mod.path ~= nil and
mod.path ~= "" and
mod.path ~= engine.get_modpath() then
if not engine.delete_dir(mod.path) then
gamedata.errormessage = fgettext("Modmgr: failed to delete \"$1\"", mod.path)
end
modmgr.refresh_globals()
else
gamedata.errormessage = fgettext("Modmgr: invalid modpath \"$1\"", mod.path)
end
end
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
--------------------------------------------------------------------------------
function modmgr.dialog_delete_mod()
local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
local retval =
"field[1.75,1;10,3;;" .. fgettext("Are you sure you want to delete \"$1\"?", mod.name) .. ";]"..
"button[4,4.2;1,0.5;dlg_delete_mod_confirm;" .. fgettext("Yes") .. "]" ..
"button[6.5,4.2;3,0.5;dlg_delete_mod_cancel;" .. fgettext("No of course not!") .. "]"
return retval
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function modmgr.preparemodlist(data) function modmgr.preparemodlist(data)
local retval = {} local retval = {}
@ -886,7 +399,7 @@ function modmgr.preparemodlist(data)
local game_mods = {} local game_mods = {}
--read global mods --read global mods
local modpath = engine.get_modpath() local modpath = core.get_modpath()
if modpath ~= nil and if modpath ~= nil and
modpath ~= "" then modpath ~= "" then
@ -922,15 +435,16 @@ function modmgr.preparemodlist(data)
key = key:sub(10) key = key:sub(10)
local element = nil local element = nil
for i=1,#retval,1 do for i=1,#retval,1 do
if retval[i].name == key then if retval[i].name == key and
not retval[i].is_modpack then
element = retval[i] element = retval[i]
break break
end end
end end
if element ~= nil then if element ~= nil then
element.enabled = engine.is_yes(value) element.enabled = core.is_yes(value)
else else
engine.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found") core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found")
end end
end end
end end
@ -938,58 +452,6 @@ function modmgr.preparemodlist(data)
return retval return retval
end end
--------------------------------------------------------------------------------
function modmgr.init_worldconfig()
modmgr.precheck()
local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
if worldspec ~= nil then
--read worldconfig
modmgr.worldconfig = modmgr.get_worldconfig(worldspec.path)
if modmgr.worldconfig.id == nil or
modmgr.worldconfig.id == "" then
modmgr.worldconfig = nil
return false
end
modmgr.modlist = 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= worldspec.path,
gameid = worldspec.gameid }
)
filterlist.set_filtercriteria(modmgr.modlist, {
hide_game=modmgr.hide_gamemods,
hide_modpackcontents= modmgr.hide_modpackcontents
})
filterlist.add_sort_mechanism(modmgr.modlist, "alphabetic", sort_mod_list)
filterlist.set_sortmode(modmgr.modlist, "alphabetic")
return true
end
return false
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function modmgr.comparemod(elem1,elem2) function modmgr.comparemod(elem1,elem2)
if elem1 == nil or elem2 == nil then if elem1 == nil or elem2 == nil then
@ -1015,29 +477,6 @@ function modmgr.comparemod(elem1,elem2)
return true return true
end end
--------------------------------------------------------------------------------
function modmgr.gettab(name)
local retval = ""
if name == "mod_mgr" then
retval = retval .. modmgr.tab()
end
if name == "dialog_rename_modpack" then
retval = retval .. modmgr.dialog_rename_modpack()
end
if name == "dialog_delete_mod" then
retval = retval .. modmgr.dialog_delete_mod()
end
if name == "dialog_configure_world" then
retval = retval .. modmgr.dialog_configure_world()
end
return retval
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function modmgr.mod_exists(basename) function modmgr.mod_exists(basename)
@ -1045,7 +484,7 @@ function modmgr.mod_exists(basename)
modmgr.refresh_globals() modmgr.refresh_globals()
end end
if filterlist.raw_index_by_uid(modmgr.global_mods,basename) > 0 then if modmgr.global_mods:raw_index_by_uid(basename) > 0 then
return true return true
end end
@ -1059,11 +498,12 @@ function modmgr.get_global_mod(idx)
return nil return nil
end end
if idx == nil or idx < 1 or idx > filterlist.size(modmgr.global_mods) then if idx == nil or idx < 1 or
idx > modmgr.global_mods:size() then
return nil return nil
end end
return filterlist.get_list(modmgr.global_mods)[idx] return modmgr.global_mods:get_list()[idx]
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -1079,8 +519,8 @@ function modmgr.refresh_globals()
nil, --filter nil, --filter
{} {}
) )
filterlist.add_sort_mechanism(modmgr.global_mods, "alphabetic", sort_mod_list) modmgr.global_mods:add_sort_mechanism("alphabetic", sort_mod_list)
filterlist.set_sortmode(modmgr.global_mods, "alphabetic") modmgr.global_mods:set_sortmode("alphabetic")
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

@ -22,15 +22,13 @@ modstore = {}
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- @function [parent=#modstore] init -- @function [parent=#modstore] init
function modstore.init() function modstore.init(size, unsortedmods, searchmods)
modstore.tabnames = {}
table.insert(modstore.tabnames,"dialog_modstore_unsorted") modstore.mods_on_unsorted_page = unsortedmods
table.insert(modstore.tabnames,"dialog_modstore_search") modstore.mods_on_search_page = searchmods
modstore.modsperpage = modstore.mods_on_unsorted_page
modstore.modsperpage = 5 modstore.basetexturedir = core.get_texturepath() .. DIR_DELIM .. "base" ..
modstore.basetexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM DIR_DELIM .. "pack" .. DIR_DELIM
modstore.lastmodtitle = "" modstore.lastmodtitle = ""
@ -79,6 +77,31 @@ function modstore.init()
) )
modstore.current_list = nil modstore.current_list = nil
modstore.tv_store = tabview_create("modstore",size,{x=-0.3,y=-0.99})
modstore.tv_store:set_global_event_handler(modstore.handle_events)
modstore.tv_store:add(
{
name = "unsorted",
caption = fgettext("Unsorted"),
cbf_formspec = modstore.unsorted_tab,
cbf_button_handler = modstore.handle_buttons,
on_change =
function() modstore.modsperpage = modstore.mods_on_unsorted_page end
}
)
modstore.tv_store:add(
{
name = "search",
caption = fgettext("Search"),
cbf_formspec = modstore.getsearchpage,
cbf_button_handler = modstore.handle_buttons,
on_change = modstore.activate_search_tab
}
)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -95,8 +118,41 @@ function modstore.nametoindex(name)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- @function [parent=#modstore] getsuccessfuldialog -- @function [parent=#modstore] showdownloading
function modstore.getsuccessfuldialog() function modstore.showdownloading(title)
local new_dlg = dialog_create("store_downloading",
function(data)
return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") ..
" " .. data.title .. " " ..
fgettext("please wait...") .. "]"
end,
function(this,fields)
if fields["btn_hidden_close_download"] ~= nil then
if fields["btn_hidden_close_download"].successfull then
modstore.lastmodentry = fields["btn_hidden_close_download"]
modstore.successfulldialog()
else
modstore.lastmodtitle = ""
end
this:delete()
return true
end
return false
end,
nil,
modstore.tv_store)
new_dlg.data.title = title
new_dlg:show()
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] successfulldialog
function modstore.successfulldialog()
local new_dlg = dialog_create("store_downloading",
function(data)
local retval = "" local retval = ""
retval = retval .. "size[6,2,true]" retval = retval .. "size[6,2,true]"
if modstore.lastmodentry ~= nil then if modstore.lastmodentry ~= nil then
@ -105,97 +161,38 @@ function modstore.getsuccessfuldialog()
retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]" retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
retval = retval .. "label[3,0.75;" .. engine.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]" retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
end end
retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]" retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]"
end,
function(this,fields)
if fields["btn_confirm_mod_successfull"] ~= nil then
this.parent:show()
this:hide()
this:delete()
return true
return retval
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] gettab
function modstore.gettab(tabname)
local retval = ""
local is_modstore_tab = false
if tabname == "dialog_modstore_unsorted" then
modstore.modsperpage = 5
retval = modstore.getmodlist(modstore.modlist_unsorted)
is_modstore_tab = true
end end
if tabname == "dialog_modstore_search" then return false
retval = modstore.getsearchpage() end,
is_modstore_tab = true nil,
end modstore.tv_store)
if is_modstore_tab then new_dlg.data.title = title
return modstore.tabheader(tabname) .. retval new_dlg:show()
end
if tabname == "modstore_mod_installed" then
return modstore.getsuccessfuldialog()
end
if tabname == "modstore_downloading" then
return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") ..
" " .. modstore.lastmodtitle .. " " ..
fgettext("please wait...") .. "]"
end
return ""
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] tabheader
function modstore.tabheader(tabname)
local retval = "size[12,10.25,true]"
retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" ..
"Unsorted,Search;" ..
modstore.nametoindex(tabname) .. ";true;false]" ..
"button[4,9.9;4,0.5;btn_modstore_close;" ..
fgettext("Close modstore") .. "]"
return retval
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- @function [parent=#modstore] handle_buttons -- @function [parent=#modstore] handle_buttons
function modstore.handle_buttons(current_tab,fields) function modstore.handle_buttons(parent, fields, name, data)
if fields["modstore_tab"] then
local index = tonumber(fields["modstore_tab"])
if index > 0 and
index <= #modstore.tabnames then
if modstore.tabnames[index] == "dialog_modstore_search" then
filterlist.set_filtercriteria(modstore.searchlist,modstore.last_search)
filterlist.refresh(modstore.searchlist)
modstore.modsperpage = 4
modstore.currentlist = {
page = 0,
pagecount =
math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
data = filterlist.get_list(modstore.searchlist),
}
end
return {
current_tab = modstore.tabnames[index],
is_dialog = true,
show_buttons = false
}
end
end
if fields["btn_modstore_page_up"] then if fields["btn_modstore_page_up"] then
if modstore.current_list ~= nil and modstore.current_list.page > 0 then if modstore.current_list ~= nil and modstore.current_list.page > 0 then
modstore.current_list.page = modstore.current_list.page - 1 modstore.current_list.page = modstore.current_list.page - 1
end end
return true
end end
if fields["btn_modstore_page_down"] then if fields["btn_modstore_page_down"] then
@ -203,34 +200,7 @@ function modstore.handle_buttons(current_tab,fields)
modstore.current_list.page <modstore.current_list.pagecount-1 then modstore.current_list.page <modstore.current_list.pagecount-1 then
modstore.current_list.page = modstore.current_list.page +1 modstore.current_list.page = modstore.current_list.page +1
end end
end return true
if fields["btn_hidden_close_download"] ~= nil then
if fields["btn_hidden_close_download"].successfull then
modstore.lastmodentry = fields["btn_hidden_close_download"]
return {
current_tab = "modstore_mod_installed",
is_dialog = true,
show_buttons = false
}
else
modstore.lastmodtitle = ""
return {
current_tab = modstore.tabnames[1],
is_dialog = true,
show_buttons = false
}
end
end
if fields["btn_confirm_mod_successfull"] then
modstore.lastmodentry = nil
modstore.lastmodtitle = ""
return {
current_tab = modstore.tabnames[1],
is_dialog = true,
show_buttons = false
}
end end
if fields["btn_modstore_search"] or if fields["btn_modstore_search"] or
@ -243,15 +213,12 @@ function modstore.handle_buttons(current_tab,fields)
pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage), pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
data = filterlist.get_list(modstore.searchlist), data = filterlist.get_list(modstore.searchlist),
} }
return true
end end
if fields["btn_modstore_close"] then if fields["btn_modstore_close"] then
return { parent:hide()
is_dialog = false, return true
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end end
for key,value in pairs(fields) do for key,value in pairs(fields) do
@ -268,23 +235,23 @@ function modstore.handle_buttons(current_tab,fields)
modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title
engine.handle_async( if not core.handle_async(
function(param) function(param)
local fullurl = core.setting_get("modstore_download_url") ..
local fullurl = engine.setting_get("modstore_download_url") ..
param.moddetails.download_url param.moddetails.download_url
if param.version ~= nil then if param.version ~= nil then
local found = false local found = false
for i=1,#param.moddetails.versions, 1 do for i=1,#param.moddetails.versions, 1 do
if param.moddetails.versions[i].date:sub(1,10) == param.version then if param.moddetails.versions[i].date:sub(1,10) == param.version then
fullurl = engine.setting_get("modstore_download_url") .. fullurl = core.setting_get("modstore_download_url") ..
param.moddetails.versions[i].download_url param.moddetails.versions[i].download_url
found = true found = true
end end
end end
if not found then if not found then
core.log("error","no download url found for version " .. dump(param.version))
return { return {
moddetails = param.moddetails, moddetails = param.moddetails,
successfull = false successfull = false
@ -292,7 +259,7 @@ function modstore.handle_buttons(current_tab,fields)
end end
end end
if engine.download_file(fullurl,param.filename) then if core.download_file(fullurl,param.filename) then
return { return {
texturename = param.texturename, texturename = param.texturename,
moddetails = param.moddetails, moddetails = param.moddetails,
@ -300,6 +267,7 @@ function modstore.handle_buttons(current_tab,fields)
successfull = true successfull = true
} }
else else
core.log("error","downloading " .. dump(fullurl) .. " failed")
return { return {
moddetails = param.moddetails, moddetails = param.moddetails,
successfull = false successfull = false
@ -313,6 +281,7 @@ function modstore.handle_buttons(current_tab,fields)
texturename = modstore.modlist_unsorted.data[i].texturename texturename = modstore.modlist_unsorted.data[i].texturename
}, },
function(result) function(result)
print("Result from async: " .. dump(result.successfull))
if result.successfull then if result.successfull then
modmgr.installmod(result.filename,result.moddetails.basename) modmgr.installmod(result.filename,result.moddetails.basename)
os.remove(result.filename) os.remove(result.filename)
@ -321,23 +290,33 @@ function modstore.handle_buttons(current_tab,fields)
end end
if gamedata.errormessage == nil then if gamedata.errormessage == nil then
engine.button_handler({btn_hidden_close_download=result}) core.button_handler({btn_hidden_close_download=result})
else else
engine.button_handler({btn_hidden_close_download={successfull=false}}) core.button_handler({btn_hidden_close_download={successfull=false}})
end
end
) then
print("ERROR: async event failed")
gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle
end
parent:hide()
modstore.showdownloading(modstore.lastmodtitle)
return true
end
end
return true
end end
end end
)
return { return false
current_tab = "modstore_downloading", end
is_dialog = true,
show_buttons = false, --------------------------------------------------------------------------------
ignore_menu_quit = true -- @function [parent=#modstore] handle_events
} function modstore.handle_events(this,event)
end if (event == "MenuQuit") then
end this:hide()
break return true
end
end end
end end
@ -349,9 +328,9 @@ function modstore.update_modlist()
modstore.modlist_unsorted.pagecount = 1 modstore.modlist_unsorted.pagecount = 1
modstore.modlist_unsorted.page = 0 modstore.modlist_unsorted.page = 0
engine.handle_async( core.handle_async(
function(param) function(param)
return engine.get_modstore_list() return core.get_modstore_list()
end, end,
nil, nil,
function(result) function(result)
@ -368,7 +347,7 @@ function modstore.update_modlist()
end end
modstore.modlist_unsorted.page = 0 modstore.modlist_unsorted.page = 0
modstore.fetchdetails() modstore.fetchdetails()
engine.event_handler("Refresh") core.event_handler("Refresh")
end end
end end
) )
@ -379,9 +358,9 @@ end
function modstore.fetchdetails() function modstore.fetchdetails()
for i=1,#modstore.modlist_unsorted.data,1 do for i=1,#modstore.modlist_unsorted.data,1 do
engine.handle_async( core.handle_async(
function(param) function(param)
param.details = engine.get_modstore_details(tostring(param.modid)) param.details = core.get_modstore_details(tostring(param.modid))
return param return param
end, end,
{ {
@ -396,7 +375,7 @@ function modstore.fetchdetails()
modstore.modlist_unsorted.data[result.listindex].id ~= nil then modstore.modlist_unsorted.data[result.listindex].id ~= nil then
modstore.modlist_unsorted.data[result.listindex].details = result.details modstore.modlist_unsorted.data[result.listindex].details = result.details
engine.event_handler("Refresh") core.event_handler("Refresh")
end end
end end
) )
@ -416,7 +395,7 @@ function modstore.getscreenshot(ypos,listentry)
end end
return "image[0,".. ypos .. ";3,2;" .. return "image[0,".. ypos .. ";3,2;" ..
engine.formspec_escape(listentry.texturename) .. "]" core.formspec_escape(listentry.texturename) .. "]"
end end
if listentry.details ~= nil and if listentry.details ~= nil and
@ -425,15 +404,15 @@ function modstore.getscreenshot(ypos,listentry)
listentry.texturename = "in progress" listentry.texturename = "in progress"
--prepare url and filename --prepare url and filename
local fullurl = engine.setting_get("modstore_download_url") .. local fullurl = core.setting_get("modstore_download_url") ..
listentry.details.screenshot_url listentry.details.screenshot_url
local filename = os.tempfolder() .. "_MID_" .. listentry.id local filename = os.tempfolder() .. "_MID_" .. listentry.id
--trigger download --trigger download
engine.handle_async( core.handle_async(
--first param is downloadfct --first param is downloadfct
function(param) function(param)
param.successfull = engine.download_file(param.fullurl,param.filename) param.successfull = core.download_file(param.fullurl,param.filename)
return param return param
end, end,
--second parameter is data passed to async job --second parameter is data passed to async job
@ -454,9 +433,9 @@ function modstore.getscreenshot(ypos,listentry)
end end
end end
if found then if found then
engine.event_handler("Refresh") core.event_handler("Refresh")
else else
engine.log("error","got screenshot but didn't find matching mod: " .. result.modid) core.log("error","got screenshot but didn't find matching mod: " .. result.modid)
end end
end end
end end
@ -466,7 +445,7 @@ function modstore.getscreenshot(ypos,listentry)
if listentry.texturename ~= nil and if listentry.texturename ~= nil and
listentry.texturename ~= "in progress" then listentry.texturename ~= "in progress" then
return "image[0,".. ypos .. ";3,2;" .. return "image[0,".. ypos .. ";3,2;" ..
engine.formspec_escape(listentry.texturename) .. "]" core.formspec_escape(listentry.texturename) .. "]"
end end
return "" return ""
@ -484,12 +463,12 @@ function modstore.getshortmodinfo(ypos,listentry,details)
--title + author --title + author
retval = retval .."label[2.75," .. ypos .. ";" .. retval = retval .."label[2.75," .. ypos .. ";" ..
engine.formspec_escape(details.title) .. " (" .. details.author .. ")]" core.formspec_escape(details.title) .. " (" .. details.author .. ")]"
--description --description
local descriptiony = ypos + 0.5 local descriptiony = ypos + 0.5
retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" .. retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" ..
engine.formspec_escape(details.description) .. ";]" core.formspec_escape(details.description) .. ";]"
--rating --rating
local ratingy = ypos local ratingy = ypos
@ -531,28 +510,31 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
--@function [parent=#modstore] getmodlist --@function [parent=#modstore] getmodlist
function modstore.getmodlist(list,yoffset) function modstore.getmodlist(list,yoffset)
modstore.current_list = list modstore.current_list = list
if #list.data == 0 then
return ""
end
if yoffset == nil then if yoffset == nil then
yoffset = 0 yoffset = 0
end end
local sb_y_start = 0.2 + yoffset
local sb_y_end = (modstore.modsperpage * 1.75) + ((modstore.modsperpage-1) * 0.15)
local close_button = "button[4," .. (sb_y_end + 0.3 + yoffset) ..
";4,0.5;btn_modstore_close;" .. fgettext("Close store") .. "]"
if #list.data == 0 then
return close_button
end
local scrollbar = "" local scrollbar = ""
scrollbar = scrollbar .. "label[0.1,9.5;" scrollbar = scrollbar .. "label[0.1,".. (sb_y_end + 0.25 + yoffset) ..";"
.. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]" .. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]"
scrollbar = scrollbar .. "box[11.6," .. (yoffset + 0.35) .. ";0.28," scrollbar = scrollbar .. "box[11.6," .. sb_y_start .. ";0.28," .. sb_y_end .. ";#000000]"
.. (8.6 - yoffset) .. ";#000000]" local scrollbarpos = (sb_y_start + 0.5) +
local scrollbarpos = (yoffset + 0.75) + ((sb_y_end -1.6)/(list.pagecount-1)) * list.page
((7.7 -yoffset)/(list.pagecount-1)) * list.page
scrollbar = scrollbar .. "box[11.6," ..scrollbarpos .. ";0.28,0.5;#32CD32]" scrollbar = scrollbar .. "box[11.6," ..scrollbarpos .. ";0.28,0.5;#32CD32]"
scrollbar = scrollbar .. "button[11.6," .. (yoffset + (0.3)) scrollbar = scrollbar .. "button[11.6," .. (sb_y_start)
.. ";0.5,0.5;btn_modstore_page_up;^]" .. ";0.5,0.5;btn_modstore_page_up;^]"
scrollbar = scrollbar .. "button[11.6," .. 9.0 scrollbar = scrollbar .. "button[11.6," .. (sb_y_start + sb_y_end - 0.5)
.. ";0.5,0.5;btn_modstore_page_down;v]" .. ";0.5,0.5;btn_modstore_page_down;v]"
local retval = "" local retval = ""
@ -585,12 +567,12 @@ function modstore.getmodlist(list,yoffset)
end end
end end
return retval .. scrollbar return retval .. scrollbar .. close_button
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
--@function [parent=#modstore] getsearchpage --@function [parent=#modstore] getsearchpage
function modstore.getsearchpage() function modstore.getsearchpage(tabview, name, tabdata)
local retval = "" local retval = ""
local search = "" local search = ""
@ -602,9 +584,6 @@ function modstore.getsearchpage()
"button[9.5,0.2;2.5,0.5;btn_modstore_search;".. fgettext("Search") .. "]" .. "button[9.5,0.2;2.5,0.5;btn_modstore_search;".. fgettext("Search") .. "]" ..
"field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]" "field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]"
--show 4 mods only
modstore.modsperpage = 4
retval = retval .. retval = retval ..
modstore.getmodlist( modstore.getmodlist(
modstore.currentlist, modstore.currentlist,
@ -613,3 +592,27 @@ function modstore.getsearchpage()
return retval; return retval;
end end
--------------------------------------------------------------------------------
--@function [parent=#modstore] unsorted_tab
function modstore.unsorted_tab()
return modstore.getmodlist(modstore.modlist_unsorted)
end
--------------------------------------------------------------------------------
--@function [parent=#modstore] activate_search_tab
function modstore.activate_search_tab(type, old_tab, new_tab)
if old_tab == new_tab then
return
end
filterlist.set_filtercriteria(modstore.searchlist,modstore.last_search)
filterlist.refresh(modstore.searchlist)
modstore.modsperpage = modstore.mods_on_search_page
modstore.currentlist = {
page = 0,
pagecount =
math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
data = filterlist.get_list(modstore.searchlist),
}
end

@ -0,0 +1,62 @@
--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.
--------------------------------------------------------------------------------
tab_credits = {
name = "credits",
caption = fgettext("Credits"),
cbf_formspec = function (tabview, name, tabdata)
local logofile = defaulttexturedir .. "logo.png"
return "vertlabel[0,-0.5;CREDITS]" ..
"label[0.5,3;Minetest " .. core.get_version() .. "]" ..
"label[0.5,3.3;http://minetest.net]" ..
"image[0.5,1;" .. core.formspec_escape(logofile) .. "]" ..
"textlist[3.5,-0.25;8.5,5.8;list_credits;" ..
"#FFFF00" .. fgettext("Core Developers") .."," ..
"Perttu Ahola (celeron55) <celeron55@gmail.com>,"..
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>,"..
"PilzAdam <pilzadam@minetest.net>," ..
"Ilya Zhuravlev (xyz) <xyz@minetest.net>,"..
"Lisa Milne (darkrose) <lisa@ltmnet.com>,"..
"Maciej Kasatkin (RealBadAngel) <mk@realbadangel.pl>,"..
"proller <proler@gmail.com>,"..
"sfan5 <sfan5@live.de>,"..
"kahrl <kahrl@gmx.net>,"..
"sapier,"..
"ShadowNinja <shadowninja@minetest.net>,"..
"Nathanael Courant (Nore/Novatux) <nore@mesecons.net>,"..
"BlockMen,"..
","..
"#FFFF00" .. fgettext("Active Contributors") .. "," ..
"Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>,"..
"Jurgen Doser (doserj) <jurgen.doser@gmail.com>,"..
"Jeija <jeija@mesecons.net>,"..
"MirceaKitsune <mirceakitsune@gmail.com>,"..
"dannydark <the_skeleton_of_a_child@yahoo.co.uk>,"..
"0gb.us <0gb.us@0gb.us>,"..
"," ..
"#FFFF00" .. fgettext("Previous Contributors") .. "," ..
"Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com>,"..
"Jonathan Neuschafer <j.neuschaefer@gmx.net>,"..
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>,"..
"Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>,"..
"matttpt <matttpt@gmail.com>,"..
"JacobF <queatz@gmail.com>,"..
";0;true]"
end
}

@ -0,0 +1,170 @@
--Minetest
--Copyright (C) 2014 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(tabview, name, tabdata)
if modmgr.global_mods == nil then
modmgr.refresh_globals()
end
if tabdata.selected_mod == nil then
tabdata.selected_mod = 1
end
local retval =
"vertlabel[0,-0.25;".. fgettext("MODS") .. "]" ..
"label[0.8,-0.25;".. fgettext("Installed Mods:") .. "]" ..
"textlist[0.75,0.25;4.5,4;modlist;" ..
modmgr.render_modlist(modmgr.global_mods) ..
";" .. tabdata.selected_mod .. "]"
retval = retval ..
"label[0.8,4.2;" .. fgettext("Add mod:") .. "]" ..
-- TODO Disabled due to upcoming release 0.4.8 and irrlicht messing up localization
-- "button[0.75,4.85;1.8,0.5;btn_mod_mgr_install_local;".. fgettext("Local install") .. "]" ..
"button[2.45,4.85;3.05,0.5;btn_modstore;".. fgettext("Online mod repository") .. "]"
local selected_mod = nil
if filterlist.size(modmgr.global_mods) >= tabdata.selected_mod then
selected_mod = modmgr.global_mods:get_list()[tabdata.selected_mod]
end
if selected_mod ~= nil then
local modscreenshot = nil
--check for screenshot beeing available
local screenshotfilename = selected_mod.path .. DIR_DELIM .. "screenshot.png"
local error = nil
local screenshotfile,error = io.open(screenshotfilename,"r")
if error == nil then
screenshotfile:close()
modscreenshot = screenshotfilename
end
if modscreenshot == nil then
modscreenshot = modstore.basetexturedir .. "no_screenshot.png"
end
retval = retval
.. "image[5.5,0;3,2;" .. core.formspec_escape(modscreenshot) .. "]"
.. "label[8.25,0.6;" .. selected_mod.name .. "]"
local descriptionlines = nil
error = nil
local descriptionfilename = selected_mod.path .. "description.txt"
local descriptionfile,error = io.open(descriptionfilename,"r")
if error == nil then
local descriptiontext = descriptionfile:read("*all")
descriptionlines = core.splittext(descriptiontext,42)
descriptionfile:close()
else
descriptionlines = {}
table.insert(descriptionlines,fgettext("No mod description available"))
end
retval = retval ..
"label[5.5,1.7;".. fgettext("Mod information:") .. "]" ..
"textlist[5.5,2.2;6.2,2.4;description;"
for i=1,#descriptionlines,1 do
retval = retval .. core.formspec_escape(descriptionlines[i]) .. ","
end
if selected_mod.is_modpack then
retval = retval .. ";0]" ..
"button[10,4.85;2,0.5;btn_mod_mgr_rename_modpack;" ..
fgettext("Rename") .. "]"
retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;"
.. fgettext("Uninstall selected modpack") .. "]"
else
--show dependencies
retval = retval .. ",Depends:,"
local toadd = modmgr.get_dependencies(selected_mod.path)
retval = retval .. toadd .. ";0]"
retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;"
.. fgettext("Uninstall selected mod") .. "]"
end
end
return retval
end
--------------------------------------------------------------------------------
local function handle_buttons(tabview, fields, tabname, tabdata)
if fields["modlist"] ~= nil then
local event = core.explode_textlist_event(fields["modlist"])
tabdata.selected_mod = event.index
return true
end
if fields["btn_mod_mgr_install_local"] ~= nil then
core.show_file_open_dialog("mod_mgt_open_dlg",fgettext("Select Mod File:"))
return true
end
if fields["btn_modstore"] ~= nil then
local modstore_ui = ui.find_by_name("modstore")
if modstore_ui ~= nil then
tabview:hide()
modstore.update_modlist()
modstore_ui:show()
else
print("modstore ui element not found")
end
return true
end
if fields["btn_mod_mgr_rename_modpack"] ~= nil then
local dlg_renamemp = create_rename_modpack_dlg(tabdata.selected_mod)
dlg_renamemp:set_parent(tabview)
tabview:hide()
dlg_renamemp:show()
return true
end
if fields["btn_mod_mgr_delete_mod"] ~= nil then
local dlg_delmod = create_delete_mod_dlg(tabdata.selected_mod)
dlg_delmod:set_parent(tabview)
tabview:hide()
dlg_delmod:show()
return true
end
if fields["mod_mgt_open_dlg_accepted"] ~= nil and
fields["mod_mgt_open_dlg_accepted"] ~= "" then
modmgr.installmod(fields["mod_mgt_open_dlg_accepted"],nil)
return true
end
return false
end
--------------------------------------------------------------------------------
tab_mods = {
name = "mods",
caption = fgettext("Mods"),
cbf_formspec = get_formspec,
cbf_button_handler = handle_buttons,
on_change = gamemgr.update_gamelist
}

@ -0,0 +1,229 @@
--Minetest
--Copyright (C) 2014 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(tabview, name, tabdata)
local render_details = core.is_yes(core.setting_getbool("public_serverlist"))
local retval =
"vertlabel[0,-0.25;".. fgettext("CLIENT") .. "]" ..
"label[1,-0.25;".. fgettext("Favorites:") .. "]"..
"label[1,4.25;".. fgettext("Address/Port") .. "]"..
"label[9,2.75;".. fgettext("Name/Password") .. "]" ..
"field[1.25,5.25;5.5,0.5;te_address;;" ..core.setting_get("address") .."]" ..
"field[6.75,5.25;2.25,0.5;te_port;;" ..core.setting_get("remote_port") .."]" ..
"checkbox[1,3.6;cb_public_serverlist;".. fgettext("Public Serverlist") .. ";" ..
dump(core.setting_getbool("public_serverlist")) .. "]"
if not core.setting_getbool("public_serverlist") then
retval = retval ..
"button[6.45,3.95;2.25,0.5;btn_delete_favorite;".. fgettext("Delete") .. "]"
end
retval = retval ..
"button[9,4.95;2.5,0.5;btn_mp_connect;".. fgettext("Connect") .. "]" ..
"field[9.3,3.75;2.5,0.5;te_name;;" ..core.setting_get("name") .."]" ..
"pwdfield[9.3,4.5;2.5,0.5;te_pwd;]" ..
"textarea[9.3,0.25;2.5,2.75;;"
if menudata.fav_selected ~= nil and
menudata.favorites[menu.fav_selected].description ~= nil then
retval = retval ..
core.formspec_escape(menu.favorites[menu.fav_selected].description,true)
end
retval = retval ..
";]"
--favourites
retval = retval ..
"textlist[1,0.35;7.5,3.35;favourites;"
if #menudata.favorites > 0 then
retval = retval .. render_favorite(menudata.favorites[1],render_details)
for i=2,#menudata.favorites,1 do
retval = retval .. "," .. render_favorite(menudata.favorites[i],render_details)
end
end
if tabdata.fav_selected ~= nil then
retval = retval .. ";" .. tabdata.fav_selected .. "]"
else
retval = retval .. ";0]"
end
return retval
end
--------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata)
if fields["te_name"] ~= nil then
gamedata.playername = fields["te_name"]
core.setting_set("name", fields["te_name"])
end
if fields["favourites"] ~= nil then
local event = core.explode_textlist_event(fields["favourites"])
if event.type == "DCL" then
if event.index <= #menudata.favorites then
gamedata.address = menudata.favorites[event.index].address
gamedata.port = menudata.favorites[event.index].port
gamedata.playername = fields["te_name"]
if fields["te_pwd"] ~= nil then
gamedata.password = fields["te_pwd"]
end
gamedata.selected_world = 0
if menudata.favorites ~= nil then
gamedata.servername = menudata.favorites[event.index].name
gamedata.serverdescription = menudata.favorites[event.index].description
end
if gamedata.address ~= nil and
gamedata.port ~= nil then
core.setting_set("address",gamedata.address)
core.setting_set("remote_port",gamedata.port)
core.start()
end
end
return true
end
if event.type == "CHG" then
if event.index <= #menudata.favorites then
local address = menudata.favorites[event.index].address
local port = menudata.favorites[event.index].port
if address ~= nil and
port ~= nil then
core.setting_set("address",address)
core.setting_set("remote_port",port)
end
tabdata.fav_selected = event.index
end
return true
end
end
if fields["key_up"] ~= nil or
fields["key_down"] ~= nil then
local fav_idx = core.get_textlist_index("favourites")
if fav_idx ~= nil then
if fields["key_up"] ~= nil and fav_idx > 1 then
fav_idx = fav_idx -1
else if fields["key_down"] and fav_idx < #menudata.favorites then
fav_idx = fav_idx +1
end end
else
fav_idx = 1
end
local address = menudata.favorites[fav_idx].address
local port = menudata.favorites[fav_idx].port
if address ~= nil and
port ~= nil then
core.setting_set("address",address)
core.setting_set("remote_port",port)
end
tabdata.fav_selected = fav_idx
return true
end
if fields["cb_public_serverlist"] ~= nil then
core.setting_set("public_serverlist", fields["cb_public_serverlist"])
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites()
else
menudata.favorites = core.get_favorites("local")
end
tabdata.fav_selected = nil
return true
end
if fields["btn_delete_favorite"] ~= nil then
local current_favourite = core.get_textlist_index("favourites")
if current_favourite == nil then return end
core.delete_favorite(current_favourite)
menudata.favorites = core.get_favorites()
tabdata.fav_selected = nil
core.setting_set("address","")
core.setting_set("remote_port","30000")
return true
end
if fields["btn_mp_connect"] ~= nil or
fields["key_enter"] ~= nil then
gamedata.playername = fields["te_name"]
gamedata.password = fields["te_pwd"]
gamedata.address = fields["te_address"]
gamedata.port = fields["te_port"]
local fav_idx = core.get_textlist_index("favourites")
if fav_idx ~= nil and fav_idx <= #menudata.favorites and
menudata.favorites[fav_idx].address == fields["te_address"] and
menudata.favorites[fav_idx].port == fields["te_port"] then
gamedata.servername = menudata.favorites[fav_idx].name
gamedata.serverdescription = menudata.favorites[fav_idx].description
else
gamedata.servername = ""
gamedata.serverdescription = ""
end
gamedata.selected_world = 0
core.setting_set("address", fields["te_address"])
core.setting_set("remote_port",fields["te_port"])
core.start()
return true
end
return false
end
local function on_change(type,old_tab,new_tab)
if type == "LEAVE" then
return
end
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites()
else
menudata.favorites = core.get_favorites("local")
end
end
--------------------------------------------------------------------------------
tab_multiplayer = {
name = "multiplayer",
caption = fgettext("Client"),
cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler,
on_change = on_change
}

@ -0,0 +1,173 @@
--Minetest
--Copyright (C) 2014 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(tabview, name, tabdata)
local index = menudata.worldlist:get_current_index(
tonumber(core.setting_get("mainmenu_last_selected_world"))
)
local retval =
"button[4,4.15;2.6,0.5;world_delete;".. fgettext("Delete") .. "]" ..
"button[6.5,4.15;2.8,0.5;world_create;".. fgettext("New") .. "]" ..
"button[9.2,4.15;2.55,0.5;world_configure;".. fgettext("Configure") .. "]" ..
"button[8.5,4.9;3.25,0.5;start_server;".. fgettext("Start Game") .. "]" ..
"label[4,-0.25;".. fgettext("Select World:") .. "]"..
"vertlabel[0,-0.25;".. fgettext("START SERVER") .. "]" ..
"checkbox[0.5,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
dump(core.setting_getbool("creative_mode")) .. "]"..
"checkbox[0.5,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.setting_getbool("enable_damage")) .. "]"..
"checkbox[0.5,1.15;cb_server_announce;".. fgettext("Public") .. ";" ..
dump(core.setting_getbool("server_announce")) .. "]"..
"field[0.8,3.2;3.5,0.5;te_playername;".. fgettext("Name") .. ";" ..
core.setting_get("name") .. "]" ..
"pwdfield[0.8,4.2;3.5,0.5;te_passwd;".. fgettext("Password") .. "]"
local bind_addr = core.setting_get("bind_address")
if bind_addr ~= nil and bind_addr ~= "" then
retval = retval ..
"field[0.8,5.2;2.25,0.5;te_serveraddr;".. fgettext("Bind Address") .. ";" ..
core.setting_get("bind_address") .."]" ..
"field[3.05,5.2;1.25,0.5;te_serverport;".. fgettext("Port") .. ";" ..
core.setting_get("port") .."]"
else
retval = retval ..
"field[0.8,5.2;3.5,0.5;te_serverport;".. fgettext("Server Port") .. ";" ..
core.setting_get("port") .."]"
end
retval = retval ..
"textlist[4,0.25;7.5,3.7;srv_worlds;" ..
menu_render_worldlist() ..
";" .. index .. "]"
return retval
end
--------------------------------------------------------------------------------
local function main_button_handler(this, fields, name, tabdata)
local world_doubleclick = false
if fields["srv_worlds"] ~= nil then
local event = core.explode_textlist_event(fields["srv_worlds"])
if event.type == "DCL" then
world_doubleclick = true
end
if event.type == "CHG" then
core.setting_set("mainmenu_last_selected_world",
menudata.worldlist:get_raw_index(core.get_textlist_index("srv_worlds")))
end
end
if menu_handle_key_up_down(fields,"srv_worlds","mainmenu_last_selected_world") then
return true
end
if fields["cb_creative_mode"] then
core.setting_set("creative_mode", fields["cb_creative_mode"])
end
if fields["cb_enable_damage"] then
core.setting_set("enable_damage", fields["cb_enable_damage"])
end
if fields["cb_server_announce"] then
core.setting_set("server_announce", fields["cb_server_announce"])
end
if fields["start_server"] ~= nil or
world_doubleclick or
fields["key_enter"] then
local selected = core.get_textlist_index("srv_worlds")
if selected ~= nil then
gamedata.playername = fields["te_playername"]
gamedata.password = fields["te_passwd"]
gamedata.port = fields["te_serverport"]
gamedata.address = ""
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
core.setting_set("port",gamedata.port)
if fields["te_serveraddr"] ~= nil then
core.setting_set("bind_address",fields["te_serveraddr"])
end
--update last game
local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
local game,index = gamemgr.find_by_gameid(world.gameid)
core.setting_set("menu_last_game",game.id)
core.start()
end
end
if fields["world_create"] ~= nil then
print("create world dialog")
local create_world_dlg = create_create_world_dlg(true)
create_world_dlg:set_parent(this)
create_world_dlg:show()
this:hide()
return true
end
if fields["world_delete"] ~= nil then
local selected = core.get_textlist_index("srv_worlds")
if selected ~= nil and
selected <= menudata.worldlist:size() then
local world = menudata.worldlist:get_list()[selected]
if world ~= nil and
world.name ~= nil and
world.name ~= "" then
local index = menudata.worldlist:get_raw_index(selected)
local delete_world_dlg = create_delete_world_dlg(world.name,index)
delete_world_dlg:set_parent(this)
delete_world_dlg:show()
this:hide()
end
end
return true
end
if fields["world_configure"] ~= nil then
local selected = core.get_textlist_index("srv_worlds")
if selected ~= nil then
local configdialog =
create_configure_world_dlg(
menudata.worldlist:get_raw_index(selected))
if (configdialog ~= nil) then
configdialog:set_parent(this)
configdialog:show()
this:hide()
end
end
return true
end
return false
end
--------------------------------------------------------------------------------
tab_server = {
name = "server",
caption = fgettext("Server"),
cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler,
on_change = nil
}

@ -0,0 +1,247 @@
--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 dlg_confirm_reset_formspec(data)
local retval =
"size[8,3]" ..
"label[1,1;".. fgettext("Are you sure to reset your singleplayer world?") .. "]"..
"button[1,2;2.6,0.5;dlg_reset_singleplayer_confirm;"..
fgettext("Yes") .. "]" ..
"button[4,2;2.8,0.5;dlg_reset_singleplayer_cancel;"..
fgettext("No!!!") .. "]"
return retval
end
local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)
if fields["dlg_reset_singleplayer_confirm"] ~= nil then
local worldlist = core.get_worlds()
local found_singleplayerworld = false
for i=1,#worldlist,1 do
if worldlist[i].name == "singleplayerworld" then
found_singleplayerworld = true
gamedata.worldindex = i
end
end
if found_singleplayerworld then
core.delete_world(gamedata.worldindex)
end
core.create_world("singleplayerworld", 1)
worldlist = core.get_worlds()
found_singleplayerworld = false
for i=1,#worldlist,1 do
if worldlist[i].name == "singleplayerworld" then
found_singleplayerworld = true
gamedata.worldindex = i
end
end
end
this.parent:show()
this:hide()
this:delete()
end
local function showconfirm_reset(tabview)
local new_dlg = dialog_create("reset_spworld",
dlg_confirm_reset_formspec,
dlg_confirm_reset_btnhandler,
nil,
tabview)
tabview:hide()
new_dlg:show()
end
local function formspec(tabview, name, tabdata)
local tab_string =
"vertlabel[0,0;" .. fgettext("SETTINGS") .. "]" ..
"box[0.75,0;3.25,4;#999999]" ..
"checkbox[1,0;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";"
.. dump(core.setting_getbool("new_style_leaves")) .. "]"..
"checkbox[1,0.5;cb_smooth_lighting;".. fgettext("Smooth Lighting")
.. ";".. dump(core.setting_getbool("smooth_lighting")) .. "]"..
"checkbox[1,1;cb_3d_clouds;".. fgettext("3D Clouds") .. ";"
.. dump(core.setting_getbool("enable_3d_clouds")) .. "]"..
"checkbox[1,1.5;cb_opaque_water;".. fgettext("Opaque Water") .. ";"
.. dump(core.setting_getbool("opaque_water")) .. "]"..
"checkbox[1,2.0;cb_pre_ivis;".. fgettext("Preload item visuals") .. ";"
.. dump(core.setting_getbool("preload_item_visuals")) .. "]"..
"checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";"
.. dump(core.setting_getbool("enable_particles")) .. "]"..
"checkbox[1,3.0;cb_finite_liquid;".. fgettext("Finite Liquid") .. ";"
.. dump(core.setting_getbool("liquid_finite")) .. "]"..
"box[4.25,0;3.25,2.5;#999999]" ..
"checkbox[4.5,0;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";"
.. dump(core.setting_getbool("mip_map")) .. "]"..
"checkbox[4.5,0.5;cb_anisotrophic;".. fgettext("Anisotropic Filtering") .. ";"
.. dump(core.setting_getbool("anisotropic_filter")) .. "]"..
"checkbox[4.5,1.0;cb_bilinear;".. fgettext("Bi-Linear Filtering") .. ";"
.. dump(core.setting_getbool("bilinear_filter")) .. "]"..
"checkbox[4.5,1.5;cb_trilinear;".. fgettext("Tri-Linear Filtering") .. ";"
.. dump(core.setting_getbool("trilinear_filter")) .. "]"..
"box[7.75,0;4,3.5;#999999]" ..
"checkbox[8,0;cb_shaders;".. fgettext("Shaders") .. ";"
.. dump(core.setting_getbool("enable_shaders")) .. "]"..
"button[1,4.5;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]"
local android = false
if android then
tab_string = tab_string ..
"box[4.25,2.75;3.25,2.5;#999999]" ..
"checkbox[4.5,2.75;cb_touchscreen_target;".. fgettext("Touch free target") .. ";"
.. dump(core.setting_getbool("touchtarget")) .. "]" ..
"button[8,4.5;3.75,0.5;btn_reset_singleplayer;".. fgettext("Reset singleplayer world") .. "]"
end
if core.setting_get("touchscreen_threshold") ~= nil then
tab_string = tab_string ..
"label[4.5,3.5;" .. fgettext("Touchthreshold (px)") .. "]" ..
"dropdown[4.5,4;3;dd_touchthreshold;0,10,20,30,40,50;" ..
((tonumber(core.setting_get("touchscreen_threshold"))/10)+1) .. "]"
end
if core.setting_getbool("enable_shaders") then
tab_string = tab_string ..
"checkbox[8,0.5;cb_bumpmapping;".. fgettext("Bumpmapping") .. ";"
.. dump(core.setting_getbool("enable_bumpmapping")) .. "]"..
"checkbox[8,1.0;cb_parallax;".. fgettext("Parallax Occlusion") .. ";"
.. dump(core.setting_getbool("enable_parallax_occlusion")) .. "]"..
"checkbox[8,1.5;cb_waving_water;".. fgettext("Waving Water") .. ";"
.. dump(core.setting_getbool("enable_waving_water")) .. "]"..
"checkbox[8,2.0;cb_waving_leaves;".. fgettext("Waving Leaves") .. ";"
.. dump(core.setting_getbool("enable_waving_leaves")) .. "]"..
"checkbox[8,2.5;cb_waving_plants;".. fgettext("Waving Plants") .. ";"
.. dump(core.setting_getbool("enable_waving_plants")) .. "]"
else
tab_string = tab_string ..
"textlist[8.33,0.7;3,1;;#888888" .. fgettext("Bumpmapping") .. ";0;true]" ..
"textlist[8.33,1.2;3,1;;#888888" .. fgettext("Parallax Occlusion") .. ";0;true]" ..
"textlist[8.33,1.7;3,1;;#888888" .. fgettext("Waving Water") .. ";0;true]" ..
"textlist[8.33,2.2;3,1;;#888888" .. fgettext("Waving Leaves") .. ";0;true]" ..
"textlist[8.33,2.7;3,1;;#888888" .. fgettext("Waving Plants") .. ";0;true]"
end
return tab_string
end
--------------------------------------------------------------------------------
local function handle_settings_buttons(this, fields, tabname, tabdata)
if fields["cb_fancy_trees"] then
core.setting_set("new_style_leaves", fields["cb_fancy_trees"])
return true
end
if fields["cb_smooth_lighting"] then
core.setting_set("smooth_lighting", fields["cb_smooth_lighting"])
return true
end
if fields["cb_3d_clouds"] then
core.setting_set("enable_3d_clouds", fields["cb_3d_clouds"])
return true
end
if fields["cb_opaque_water"] then
core.setting_set("opaque_water", fields["cb_opaque_water"])
return true
end
if fields["cb_mipmapping"] then
core.setting_set("mip_map", fields["cb_mipmapping"])
return true
end
if fields["cb_anisotrophic"] then
core.setting_set("anisotropic_filter", fields["cb_anisotrophic"])
return true
end
if fields["cb_bilinear"] then
core.setting_set("bilinear_filter", fields["cb_bilinear"])
return true
end
if fields["cb_trilinear"] then
core.setting_set("trilinear_filter", fields["cb_trilinear"])
return true
end
if fields["cb_shaders"] then
if (core.setting_get("video_driver") == "direct3d8" or core.setting_get("video_driver") == "direct3d9") then
core.setting_set("enable_shaders", "false")
gamedata.errormessage = fgettext("To enable shaders the OpenGL driver needs to be used.")
else
core.setting_set("enable_shaders", fields["cb_shaders"])
end
return true
end
if fields["cb_pre_ivis"] then
core.setting_set("preload_item_visuals", fields["cb_pre_ivis"])
return true
end
if fields["cb_particles"] then
core.setting_set("enable_particles", fields["cb_particles"])
return true
end
if fields["cb_finite_liquid"] then
core.setting_set("liquid_finite", fields["cb_finite_liquid"])
return true
end
if fields["cb_bumpmapping"] then
core.setting_set("enable_bumpmapping", fields["cb_bumpmapping"])
end
if fields["cb_parallax"] then
core.setting_set("enable_parallax_occlusion", fields["cb_parallax"])
return true
end
if fields["cb_waving_water"] then
core.setting_set("enable_waving_water", fields["cb_waving_water"])
return true
end
if fields["cb_waving_leaves"] then
core.setting_set("enable_waving_leaves", fields["cb_waving_leaves"])
end
if fields["cb_waving_plants"] then
core.setting_set("enable_waving_plants", fields["cb_waving_plants"])
return true
end
if fields["btn_change_keys"] ~= nil then
core.show_keys_menu()
return true
end
if fields["cb_touchscreen_target"] then
core.setting_set("touchtarget", fields["cb_touchscreen_target"])
return true
end
if fields["dd_touchthreshold"] then
core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"])
return true
end
if fields["btn_reset_singleplayer"] then
showconfirm_reset(this)
return true
end
end
tab_settings = {
name = "settings",
caption = fgettext("Settings"),
cbf_formspec = formspec,
cbf_button_handler = handle_settings_buttons
}

@ -0,0 +1,176 @@
--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(tabview, name, tabdata)
local retval = ""
local render_details = dump(core.setting_getbool("public_serverlist"))
retval = retval ..
"label[0,3.0;".. fgettext("Address/Port") .. "]"..
"label[8,0.5;".. fgettext("Name/Password") .. "]" ..
"field[0.25,3.25;5.5,0.5;te_address;;" ..core.setting_get("address") .."]" ..
"field[5.75,3.25;2.25,0.5;te_port;;" ..core.setting_get("remote_port") .."]" ..
"checkbox[8,-0.25;cb_public_serverlist;".. fgettext("Public Serverlist") .. ";" ..
render_details .. "]"
retval = retval ..
"button[8,2.5;4,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" ..
"field[8.75,1.5;3.5,0.5;te_name;;" ..core.setting_get("name") .."]" ..
"pwdfield[8.75,2.3;3.5,0.5;te_pwd;]"
--favourites
retval = retval ..
"textlist[-0.05,0.0;7.55,2.75;favourites;"
if #menudata.favorites > 0 then
retval = retval .. render_favorite(menudata.favorites[1],render_details)
for i=2,#menudata.favorites,1 do
retval = retval .. "," .. render_favorite(menudata.favorites[i],render_details)
end
end
if tabdata.fav_selected ~= nil then
retval = retval .. ";" .. tabdata.fav_selected .. "]"
else
retval = retval .. ";0]"
end
-- separator
retval = retval ..
"box[-0.3,3.75;12.4,0.1;#FFFFFF]"
-- checkboxes
retval = retval ..
"checkbox[1.0,3.9;cb_creative;".. fgettext("Creative Mode") .. ";" ..
dump(core.setting_getbool("creative_mode")) .. "]"..
"checkbox[5.0,3.9;cb_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.setting_getbool("enable_damage")) .. "]" ..
"checkbox[8,3.9;cb_fly_mode;".. fgettext("Fly mode") .. ";" ..
dump(core.setting_getbool("free_move")) .. "]"
-- buttons
retval = retval ..
"button[3.0,4.5;6,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]"
return retval
end
--------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata)
if fields["btn_start_singleplayer"] then
gamedata.selected_world = gamedata.worldindex
gamedata.singleplayer = true
core.start()
end
if fields["favourites"] ~= nil then
local event = core.explode_textlist_event(fields["favourites"])
if event.type == "CHG" then
if event.index <= #maintab_favorites then
local address = maintab_favorites[event.index].address
local port = maintab_favorites[event.index].port
if address ~= nil and
port ~= nil then
core.setting_set("address",address)
core.setting_set("remote_port",port)
end
tabdata.fav_selected = event.index
end
end
return
end
if fields["cb_public_serverlist"] ~= nil then
core.setting_set("public_serverlist", fields["cb_public_serverlist"])
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites()
else
maintab_favorites = core.get_favorites("local")
end
return
end
if fields["cb_creative"] then
core.setting_set("creative_mode", fields["cb_creative"])
end
if fields["cb_damage"] then
core.setting_set("enable_damage", fields["cb_damage"])
end
if fields["cb_fly_mode"] then
core.setting_set("free_move", fields["cb_fly_mode"])
end
if fields["btn_mp_connect"] ~= nil or
fields["key_enter"] ~= nil then
gamedata.playername = fields["te_name"]
gamedata.password = fields["te_pwd"]
gamedata.address = fields["te_address"]
gamedata.port = fields["te_port"]
local fav_idx = core.get_textlist_index("favourites")
if fav_idx ~= nil and fav_idx <= #menudata.favorites and
menudata.favorites[fav_idx].address == fields["te_address"] and
menudata.favorites[fav_idx].port == fields["te_port"] then
gamedata.servername = menudata.favorites[fav_idx].name
gamedata.serverdescription = menudata.favorites[fav_idx].description
else
gamedata.servername = ""
gamedata.serverdescription = ""
end
gamedata.selected_world = 0
core.setting_set("address",fields["te_address"])
core.setting_set("remote_port",fields["te_port"])
core.start()
return
end
end
--------------------------------------------------------------------------------
local function on_activate(type,old_tab,new_tab)
if type == "LEAVE" then
return
end
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites()
else
menudata.favorites = core.get_favorites("local")
end
end
--------------------------------------------------------------------------------
tab_simple_main = {
name = "main",
caption = fgettext("Main"),
cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler,
on_change = on_activate
}

@ -0,0 +1,218 @@
--Minetest
--Copyright (C) 2014 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 singleplayer_refresh_gamebar()
local old_bar = ui.find_by_name("game_button_bar")
if old_bar ~= nil then
old_bar:delete()
end
local function game_buttonbar_button_handler(fields)
for key,value in pairs(fields) do
for j=1,#gamemgr.games,1 do
if ("game_btnbar_" .. gamemgr.games[j].id == key) then
mm_texture.update("singleplayer", gamemgr.games[j])
core.setting_set("menu_last_game",gamemgr.games[j].id)
menudata.worldlist:set_filtercriteria(gamemgr.games[j].id)
return true
end
end
end
end
local btnbar = buttonbar_create("game_button_bar",
game_buttonbar_button_handler,
{x=-0.3,y=5.65}, "horizontal", {x=12.4,y=1.15})
for i=1,#gamemgr.games,1 do
local btn_name = "game_btnbar_" .. gamemgr.games[i].id
local image = nil
local text = nil
if gamemgr.games[i].menuicon_path ~= nil and
gamemgr.games[i].menuicon_path ~= "" then
image = core.formspec_escape(gamemgr.games[i].menuicon_path)
else
local part1 = gamemgr.games[i].id:sub(1,5)
local part2 = gamemgr.games[i].id:sub(6,10)
local part3 = gamemgr.games[i].id:sub(11)
text = part1 .. "\n" .. part2
if part3 ~= nil and
part3 ~= "" then
text = text .. "\n" .. part3
end
end
btnbar:add_button(btn_name, text, image)
end
end
local function get_formspec(tabview, name, tabdata)
local retval = ""
local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.setting_get("mainmenu_last_selected_world"))
)
retval = retval ..
"button[4,4.15;2.6,0.5;world_delete;".. fgettext("Delete") .. "]" ..
"button[6.5,4.15;2.8,0.5;world_create;".. fgettext("New") .. "]" ..
"button[9.2,4.15;2.55,0.5;world_configure;".. fgettext("Configure") .. "]" ..
"button[8.5,4.95;3.25,0.5;play;".. fgettext("Play") .. "]" ..
"label[4,-0.25;".. fgettext("Select World:") .. "]"..
"vertlabel[0,-0.25;".. fgettext("SINGLE PLAYER") .. "]" ..
"checkbox[0.5,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
dump(core.setting_getbool("creative_mode")) .. "]"..
"checkbox[0.5,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.setting_getbool("enable_damage")) .. "]"..
"textlist[4,0.25;7.5,3.7;sp_worlds;" ..
menu_render_worldlist() ..
";" .. index .. "]"
return retval
end
local function main_button_handler(this, fields, name, tabdata)
assert(name == "singleplayer")
local world_doubleclick = false
if fields["sp_worlds"] ~= nil then
local event = core.explode_textlist_event(fields["sp_worlds"])
if event.type == "DCL" then
world_doubleclick = true
end
if event.type == "CHG" then
core.setting_set("mainmenu_last_selected_world",
menudata.worldlist:get_raw_index(core.get_textlist_index("sp_worlds")))
end
return true
end
if menu_handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world") then
return true
end
if fields["cb_creative_mode"] then
core.setting_set("creative_mode", fields["cb_creative_mode"])
return true
end
if fields["cb_enable_damage"] then
core.setting_set("enable_damage", fields["cb_enable_damage"])
return true
end
if fields["play"] ~= nil or
world_doubleclick or
fields["key_enter"] then
local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil then
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
gamedata.singleplayer = true
core.start()
end
return true
end
if fields["world_create"] ~= nil then
print("create world dialog")
local create_world_dlg = create_create_world_dlg(true)
create_world_dlg:set_parent(this)
create_world_dlg:show()
this:hide()
return true
end
if fields["world_delete"] ~= nil then
local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil and
selected <= menudata.worldlist:size() then
local world = menudata.worldlist:get_list()[selected]
if world ~= nil and
world.name ~= nil and
world.name ~= "" then
local index = menudata.worldlist:get_raw_index(selected)
local delete_world_dlg = create_delete_world_dlg(world.name,index)
delete_world_dlg:set_parent(this)
delete_world_dlg:show()
this:hide()
end
end
return true
end
if fields["world_configure"] ~= nil then
local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil then
local configdialog =
create_configure_world_dlg(
menudata.worldlist:get_raw_index(selected))
if (configdialog ~= nil) then
configdialog:set_parent(this)
configdialog:show()
this:hide()
end
end
return true
end
end
local function on_change(type, old_tab, new_tab)
local buttonbar = ui.find_by_name("game_button_bar")
if ( buttonbar == nil ) then
singleplayer_refresh_gamebar()
buttonbar = ui.find_by_name("game_button_bar")
end
if (type == "ENTER") then
local last_game_id = core.setting_get("menu_last_game")
local game, index = gamemgr.find_by_gameid(last_game_id)
if game then
menudata.worldlist:set_filtercriteria(game.id)
core.set_topleft_text(game.name)
mm_texture.update(new_tab,game)
end
buttonbar:show()
else
menudata.worldlist:set_filtercriteria(nil)
buttonbar:hide()
core.set_topleft_text("")
mm_texture.update(new_tab,nil)
end
end
--------------------------------------------------------------------------------
tab_singleplayer = {
name = "singleplayer",
caption = fgettext("Singleplayer"),
cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler,
on_change = on_change
}

@ -0,0 +1,117 @@
--Minetest
--Copyright (C) 2014 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 filter_texture_pack_list(list)
retval = {"None"}
for _,i in ipairs(list) do
if i~="base" then
table.insert(retval, i)
end
end
return retval
end
--------------------------------------------------------------------------------
local function render_texture_pack_list(list)
local retval = ""
for i, v in ipairs(list) do
if retval ~= "" then
retval = retval ..","
end
retval = retval .. core.formspec_escape(v)
end
return retval
end
--------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata)
local retval = "label[4,-0.25;".. fgettext("Select texture pack:") .. "]"..
"vertlabel[0,-0.25;".. fgettext("TEXTURE PACKS") .. "]" ..
"textlist[4,0.25;7.5,5.0;TPs;"
local current_texture_path = core.setting_get("texture_path")
local list = filter_texture_pack_list(core.get_dirlist(core.get_texturepath(), true))
local index = tonumber(core.setting_get("mainmenu_last_selected_TP"))
if index == nil then index = 1 end
if current_texture_path == "" then
retval = retval ..
render_texture_pack_list(list) ..
";" .. index .. "]"
return retval
end
local infofile = current_texture_path ..DIR_DELIM.."info.txt"
local infotext = ""
local f = io.open(infofile, "r")
if f==nil then
infotext = fgettext("No information available")
else
infotext = f:read("*all")
f:close()
end
local screenfile = current_texture_path..DIR_DELIM.."screenshot.png"
local no_screenshot = nil
if not file_exists(screenfile) then
screenfile = nil
no_screenshot = defaulttexturedir .. "no_screenshot.png"
end
return retval ..
render_texture_pack_list(list) ..
";" .. index .. "]" ..
"image[0.65,0.25;4.0,3.7;"..core.formspec_escape(screenfile or no_screenshot).."]"..
"textarea[1.0,3.25;3.7,1.5;;"..core.formspec_escape(infotext or "")..";]"
end
--------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata)
if fields["TPs"] ~= nil then
local event = core.explode_textlist_event(fields["TPs"])
if event.type == "CHG" or event.type == "DCL" then
local index = core.get_textlist_index("TPs")
core.setting_set("mainmenu_last_selected_TP",
index)
local list = filter_texture_pack_list(core.get_dirlist(core.get_texturepath(), true))
local current_index = core.get_textlist_index("TPs")
if current_index ~= nil and #list >= current_index then
local new_path = core.get_texturepath()..DIR_DELIM..list[current_index]
if list[current_index] == "None" then new_path = "" end
core.setting_set("texture_path", new_path)
end
end
return true
end
return false
end
--------------------------------------------------------------------------------
tab_texturepacks = {
name = "texturepacks",
caption = fgettext("Texturepacks"),
cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler,
on_change = nil
}

@ -20,11 +20,11 @@ mm_texture = {}
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function mm_texture.init() function mm_texture.init()
mm_texture.defaulttexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" .. mm_texture.defaulttexturedir = core.get_texturepath() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM DIR_DELIM .. "pack" .. DIR_DELIM
mm_texture.basetexturedir = mm_texture.defaulttexturedir mm_texture.basetexturedir = mm_texture.defaulttexturedir
mm_texture.texturepack = engine.setting_get("texture_path") mm_texture.texturepack = core.setting_get("texture_path")
mm_texture.gameid = nil mm_texture.gameid = nil
end end
@ -55,14 +55,14 @@ function mm_texture.reset()
mm_texture.clear("header") mm_texture.clear("header")
mm_texture.clear("footer") mm_texture.clear("footer")
engine.set_clouds(false) core.set_clouds(false)
mm_texture.set_generic("footer") mm_texture.set_generic("footer")
mm_texture.set_generic("header") mm_texture.set_generic("header")
if not have_bg and if not have_bg and
engine.setting_getbool("enable_clouds") then core.setting_getbool("menu_clouds") then
engine.set_clouds(true) core.set_clouds(true)
end end
end end
@ -81,11 +81,11 @@ function mm_texture.update_game(gamedetails)
mm_texture.clear("header") mm_texture.clear("header")
mm_texture.clear("footer") mm_texture.clear("footer")
engine.set_clouds(false) core.set_clouds(false)
if not have_bg and if not have_bg and
engine.setting_getbool("enable_clouds") then core.setting_getbool("menu_clouds") then
engine.set_clouds(true) core.set_clouds(true)
end end
mm_texture.set_game("footer",gamedetails) mm_texture.set_game("footer",gamedetails)
@ -96,7 +96,7 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function mm_texture.clear(identifier) function mm_texture.clear(identifier)
engine.set_background(identifier,"") core.set_background(identifier,"")
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -105,7 +105,7 @@ function mm_texture.set_generic(identifier)
if mm_texture.texturepack ~= nil then if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM .."menu_" .. local path = mm_texture.texturepack .. DIR_DELIM .."menu_" ..
identifier .. ".png" identifier .. ".png"
if engine.set_background(identifier,path) then if core.set_background(identifier,path) then
return true return true
end end
end end
@ -113,7 +113,7 @@ function mm_texture.set_generic(identifier)
if mm_texture.defaulttexturedir ~= nil then if mm_texture.defaulttexturedir ~= nil then
local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" .. local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" ..
identifier .. ".png" identifier .. ".png"
if engine.set_background(identifier,path) then if core.set_background(identifier,path) then
return true return true
end end
end end
@ -131,14 +131,14 @@ function mm_texture.set_game(identifier,gamedetails)
if mm_texture.texturepack ~= nil then if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM .. local path = mm_texture.texturepack .. DIR_DELIM ..
gamedetails.id .. "_menu_" .. identifier .. ".png" gamedetails.id .. "_menu_" .. identifier .. ".png"
if engine.set_background(identifier,path) then if core.set_background(identifier,path) then
return true return true
end end
end end
local path = gamedetails.path .. DIR_DELIM .."menu" .. local path = gamedetails.path .. DIR_DELIM .."menu" ..
DIR_DELIM .. identifier .. ".png" DIR_DELIM .. identifier .. ".png"
if engine.set_background(identifier,path) then if core.set_background(identifier,path) then
return true return true
end end

171
doc/fst_api.txt Normal file

@ -0,0 +1,171 @@
Formspec toolkit api 0.0.3
==========================
Formspec toolkit is a set of functions to create basic ui elements.
File: fst/ui.lua
----------------
ui.lua adds base ui interface to add additional components to.
ui.add(component) -> returns name of added component
^ add component to ui
^ component: component to add
ui.delete(component) -> true/false if a component was deleted or not
^ remove a component from ui
^ component: component to delete
ui.set_default(name)
^ set component to show if not a single component is set visible
^ name: name of component to set as default
ui.find_by_name(name) --> returns component or nil
^ find a component within ui
^ name: name of component to look for
File: fst/tabview.lua
---------------------
tabview_create(name, size, tabheaderpos) --> returns tabview component
^ create a new tabview component
^ name: name of tabview (has to be unique per ui)
^ size: size of tabview
{
x,
y
}
^ tabheaderpos: upper left position of tabheader (relative to upper left fs corner)
{
x,
y
}
Class reference tabview:
methods:
- add_tab(tab)
^ add a tab to this tabview
^ tab:
{
name = "tabname", -- name of tab to create
caption = "tab caption", -- text to show for tab header
cbf_button_handler = function(tabview, fields, tabname, tabdata), -- callback for button events
--TODO cbf_events = function(tabview, event, tabname), -- callback for events
cbf_formspec = function(tabview, name, tabdata), -- get formspec
tabsize =
{
x, -- x width
y -- y height
}, -- special size for this tab (only relevant if no parent for tabview set)
on_change = function(type,old_tab,new_tab) -- called on tab chang, type is "ENTER" or "LEAVE"
}
- set_autosave_tab(value)
^ tell tabview to automaticaly save current tabname as "tabview_name"_LAST
^ value: true/false
- set_tab(name)
^ set's tab to tab named "name", returns true/false on success
^ name: name of tab to set
- set_global_event_handler(handler)
^ set a handler to be called prior calling tab specific event handler
^ handler: function(tabview,event) --> returns true to finish event processing false to continue
- set_global_button_handler(handler)
^ set a handler to be called prior calling tab specific button handler
^ handler: function(tabview,fields) --> returns true to finish button processing false to continue
- set_parent(parent)
^ set parent to attach tabview to. TV's with parent are hidden if their parent
is hidden and they don't set their specified size.
^ parent: component to attach to
- show()
^ show tabview
- hide()
^ hide tabview
- delete()
^ delete tabview
- set_fixed_size(state)
^ true/false set to fixed size, variable size
File: fst/dialog.lua
---------------------
Only one dialog can be shown at a time. If a dialog is closed it's parent is
gonna be activated and shown again.
dialog_create(name, cbf_formspec, cbf_button_handler, cbf_events)
^ create a dialog component
^ name: name of component (unique per ui)
^ cbf_formspec: function to be called to get formspec
function(dialogdata)
^ cbf_button_handler: function to handle buttons
function(dialog, fields)
^ cbf_events: function to handle events
function(dialog, event)
Class reference dialog:
methods:
- set_parent(parent)
^ set parent to attach a dialog to
^ parent: component to attach to
- show()
^ show dialog
- hide()
^ hide dialog
- delete()
^ delete dialog from ui
members:
- data
^ variable data attached to this dialog
- parent
^ parent component to return to on exit
File: fst/buttonbar.lua
-----------------------
buttonbar_create(name, cbf_buttonhandler, pos, orientation, size)
^ create a buttonbar
^ name: name of component (unique per ui)
^ cbf_buttonhandler: function to be called on button pressed
function(buttonbar,buttonname,buttondata)
^ pos: position relative to upper left of current shown formspec
{
x,
y
}
^ orientation: "vertical" or "horizontal"
^ size: size of bar
{
width,
height
}
Class reference buttonbar:
methods:
- add_button(btn_id, caption, button_image)
- set_parent(parent)
^ set parent to attach a buttonbar to
^ parent: component to attach to
- show()
^ show buttonbar
- hide()
^ hide buttonbar
- delete()
^ delete buttonbar from ui
Developer doc:
==============
Skeleton for any component:
{
name = "some id", -- unique id
type = "toplevel", -- type of component
-- toplevel: componant can be show without additional components
-- addon: component is an addon to be shown along toplevel component
hide = function(this) end, -- called to hide the component
show = function(this) end, -- called to show the component
delete = function(this) end, -- called to delete component from ui
handle_buttons = function(this,fields) -- called upon button press
handle_events = function(this,event) -- called upon event reception
get_formspec = function(this) -- has to return formspec to be displayed
}

@ -1,4 +1,4 @@
Minetest Lua Mainmenu API Reference 0.4.9 Minetest Lua Mainmenu API Reference 0.4.10
======================================== ========================================
Introduction Introduction
@ -8,14 +8,14 @@ Description of formspec language to show your menu is in lua_api.txt
Callbacks Callbacks
--------- ---------
engine.buttonhandler(fields): called when a button is pressed. core.buttonhandler(fields): called when a button is pressed.
^ fields = {name1 = value1, name2 = value2, ...} ^ fields = {name1 = value1, name2 = value2, ...}
engine.event_handler(event) core.event_handler(event)
^ event: "MenuQuit", "KeyEnter", "ExitButton" or "EditBoxEnter" ^ event: "MenuQuit", "KeyEnter", "ExitButton" or "EditBoxEnter"
Gamedata Gamedata
-------- --------
The "gamedata" table is read when calling engine.start(). It should contain: The "gamedata" table is read when calling core.start(). It should contain:
{ {
playername = <name>, playername = <name>,
password = <password>, password = <password>,
@ -27,15 +27,15 @@ The "gamedata" table is read when calling engine.start(). It should contain:
Functions Functions
--------- ---------
engine.start() core.start()
engine.close() core.close()
Filesystem: Filesystem:
engine.get_scriptdir() core.get_scriptdir()
^ returns directory of script ^ returns directory of script
engine.get_modpath() (possible in async calls) core.get_modpath() (possible in async calls)
^ returns path to global modpath ^ returns path to global modpath
engine.get_modstore_details(modid) (possible in async calls) core.get_modstore_details(modid) (possible in async calls)
^ modid numeric id of mod in modstore ^ modid numeric id of mod in modstore
^ returns { ^ returns {
id = <numeric id of mod in modstore>, id = <numeric id of mod in modstore>,
@ -47,7 +47,7 @@ engine.get_modstore_details(modid) (possible in async calls)
license = <short description of license>, license = <short description of license>,
rating = <float value of current rating> rating = <float value of current rating>
} }
engine.get_modstore_list() (possible in async calls) core.get_modstore_list() (possible in async calls)
^ returns { ^ returns {
[1] = { [1] = {
id = <numeric id of mod in modstore>, id = <numeric id of mod in modstore>,
@ -55,60 +55,60 @@ engine.get_modstore_list() (possible in async calls)
basename = <basename for mod> basename = <basename for mod>
} }
} }
engine.get_gamepath() (possible in async calls) core.get_gamepath() (possible in async calls)
^ returns path to global gamepath ^ returns path to global gamepath
engine.get_texturepath() (possible in async calls) core.get_texturepath() (possible in async calls)
^ returns path to default textures ^ returns path to default textures
engine.get_dirlist(path,onlydirs) (possible in async calls) core.get_dirlist(path,onlydirs) (possible in async calls)
^ path to get subdirs from ^ path to get subdirs from
^ onlydirs should result contain only dirs? ^ onlydirs should result contain only dirs?
^ returns list of folders within path ^ returns list of folders within path
engine.create_dir(absolute_path) (possible in async calls) core.create_dir(absolute_path) (possible in async calls)
^ absolute_path to directory to create (needs to be absolute) ^ absolute_path to directory to create (needs to be absolute)
^ returns true/false ^ returns true/false
engine.delete_dir(absolute_path) (possible in async calls) core.delete_dir(absolute_path) (possible in async calls)
^ absolute_path to directory to delete (needs to be absolute) ^ absolute_path to directory to delete (needs to be absolute)
^ returns true/false ^ returns true/false
engine.copy_dir(source,destination,keep_soure) (possible in async calls) core.copy_dir(source,destination,keep_soure) (possible in async calls)
^ source folder ^ source folder
^ destination folder ^ destination folder
^ keep_source DEFAULT true --> if set to false source is deleted after copying ^ keep_source DEFAULT true --> if set to false source is deleted after copying
^ returns true/false ^ returns true/false
engine.extract_zip(zipfile,destination) [unzip within path required] core.extract_zip(zipfile,destination) [unzip within path required]
^ zipfile to extract ^ zipfile to extract
^ destination folder to extract to ^ destination folder to extract to
^ returns true/false ^ returns true/false
engine.download_file(url,target) (possible in async calls) core.download_file(url,target) (possible in async calls)
^ url to download ^ url to download
^ target to store to ^ target to store to
^ returns true/false ^ returns true/false
engine.get_version() (possible in async calls) core.get_version() (possible in async calls)
^ returns current core version ^ returns current core version
engine.sound_play(spec, looped) -> handle core.sound_play(spec, looped) -> handle
^ spec = SimpleSoundSpec (see lua-api.txt) ^ spec = SimpleSoundSpec (see lua-api.txt)
^ looped = bool ^ looped = bool
engine.sound_stop(handle) core.sound_stop(handle)
Formspec: Formspec:
engine.update_formspec(formspec) core.update_formspec(formspec)
engine.get_table_index(tablename) -> index core.get_table_index(tablename) -> index
^ can also handle textlists ^ can also handle textlists
engine.formspec_escape(string) -> string core.formspec_escape(string) -> string
^ escapes characters [ ] \ , ; that can not be used in formspecs ^ escapes characters [ ] \ , ; that can not be used in formspecs
engine.explode_table_event(string) -> table core.explode_table_event(string) -> table
^ returns e.g. {type="CHG", row=1, column=2} ^ returns e.g. {type="CHG", row=1, column=2}
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click) ^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
engine.explode_textlist_event(string) -> table core.explode_textlist_event(string) -> table
^ returns e.g. {type="CHG", index=1} ^ returns e.g. {type="CHG", index=1}
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click) ^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
GUI: GUI:
engine.set_background(type, texturepath) core.set_background(type, texturepath)
^ type: "background", "overlay", "header" or "footer" ^ type: "background", "overlay", "header" or "footer"
engine.set_clouds(<true/false>) core.set_clouds(<true/false>)
engine.set_topleft_text(text) core.set_topleft_text(text)
engine.show_keys_menu() core.show_keys_menu()
engine.file_open_dialog(formname,caption) core.file_open_dialog(formname,caption)
^ shows a file open dialog ^ shows a file open dialog
^ formname is base name of dialog response returned in fields ^ formname is base name of dialog response returned in fields
^ -if dialog was accepted "_accepted" ^ -if dialog was accepted "_accepted"
@ -116,7 +116,7 @@ engine.file_open_dialog(formname,caption)
^ -if dialog was canceled "_cancelled" ^ -if dialog was canceled "_cancelled"
^ will be added to fieldname value is set to formname itself ^ will be added to fieldname value is set to formname itself
^ returns nil or selected file/folder ^ returns nil or selected file/folder
engine.get_screen_info() core.get_screen_info()
^ returns { ^ returns {
density = <screen density 0.75,1.0,2.0,3.0 ... (dpi)>, density = <screen density 0.75,1.0,2.0,3.0 ... (dpi)>,
display_width = <width of display>, display_width = <width of display>,
@ -126,7 +126,7 @@ engine.get_screen_info()
} }
Games: Games:
engine.get_game(index) core.get_game(index)
^ returns { ^ returns {
id = <id>, id = <id>,
path = <full path to game>, path = <full path to game>,
@ -136,10 +136,10 @@ engine.get_game(index)
DEPRECATED: DEPRECATED:
addon_mods_paths = {[1] = <path>,}, addon_mods_paths = {[1] = <path>,},
} }
engine.get_games() -> table of all games in upper format (possible in async calls) core.get_games() -> table of all games in upper format (possible in async calls)
Favorites: Favorites:
engine.get_favorites(location) -> list of favorites (possible in async calls) core.get_favorites(location) -> list of favorites (possible in async calls)
^ location: "local" or "online" ^ location: "local" or "online"
^ returns { ^ returns {
[1] = { [1] = {
@ -156,24 +156,24 @@ engine.get_favorites(location) -> list of favorites (possible in async calls)
port = <port> port = <port>
}, },
} }
engine.delete_favorite(id, location) -> success core.delete_favorite(id, location) -> success
Logging: Logging:
engine.debug(line) (possible in async calls) core.debug(line) (possible in async calls)
^ Always printed to stderr and logfile (print() is redirected here) ^ Always printed to stderr and logfile (print() is redirected here)
engine.log(line) (possible in async calls) core.log(line) (possible in async calls)
engine.log(loglevel, line) (possible in async calls) core.log(loglevel, line) (possible in async calls)
^ loglevel one of "error", "action", "info", "verbose" ^ loglevel one of "error", "action", "info", "verbose"
Settings: Settings:
engine.setting_set(name, value) core.setting_set(name, value)
engine.setting_get(name) -> string or nil (possible in async calls) core.setting_get(name) -> string or nil (possible in async calls)
engine.setting_setbool(name, value) core.setting_setbool(name, value)
engine.setting_getbool(name) -> bool or nil (possible in async calls) core.setting_getbool(name) -> bool or nil (possible in async calls)
engine.setting_save() -> nil, save all settings to config file core.setting_save() -> nil, save all settings to config file
Worlds: Worlds:
engine.get_worlds() -> list of worlds (possible in async calls) core.get_worlds() -> list of worlds (possible in async calls)
^ returns { ^ returns {
[1] = { [1] = {
path = <full path to world>, path = <full path to world>,
@ -181,16 +181,16 @@ engine.get_worlds() -> list of worlds (possible in async calls)
gameid = <gameid of world>, gameid = <gameid of world>,
}, },
} }
engine.create_world(worldname, gameid) core.create_world(worldname, gameid)
engine.delete_world(index) core.delete_world(index)
Helpers: Helpers:
engine.gettext(string) -> string core.gettext(string) -> string
^ look up the translation of a string in the gettext message catalog ^ look up the translation of a string in the gettext message catalog
fgettext(string, ...) -> string fgettext(string, ...) -> string
^ call engine.gettext(string), replace "$1"..."$9" with the given ^ call core.gettext(string), replace "$1"..."$9" with the given
^ extra arguments, call engine.formspec_escape and return the result ^ extra arguments, call core.formspec_escape and return the result
engine.parse_json(string[, nullvalue]) -> something (possible in async calls) core.parse_json(string[, nullvalue]) -> something (possible in async calls)
^ see core.parse_json (lua_api.txt) ^ see core.parse_json (lua_api.txt)
dump(obj, dumped={}) dump(obj, dumped={})
^ Return object serialized as a string ^ Return object serialized as a string
@ -202,7 +202,7 @@ core.is_yes(arg) (possible in async calls)
^ returns whether arg can be interpreted as yes ^ returns whether arg can be interpreted as yes
Async: Async:
engine.handle_async(async_job,parameters,finished) core.handle_async(async_job,parameters,finished)
^ execute a function asynchronously ^ execute a function asynchronously
^ async_job is a function receiving one parameter and returning one parameter ^ async_job is a function receiving one parameter and returning one parameter
^ parameters parameter table passed to async_job ^ parameters parameter table passed to async_job
@ -212,8 +212,8 @@ engine.handle_async(async_job,parameters,finished)
Limitations of Async operations Limitations of Async operations
-No access to global lua variables, don't even try -No access to global lua variables, don't even try
-Limited set of available functions -Limited set of available functions
e.g. No access to functions modifying menu like engine.start,engine.close, e.g. No access to functions modifying menu like core.start,core.close,
engine.file_open_dialog core.file_open_dialog
Class reference Class reference