diff options
author | sapier <Sapier at GMX dot net> | 2014-04-18 15:39:15 +0200 |
---|---|---|
committer | sapier <Sapier at GMX dot net> | 2014-05-16 22:57:14 +0200 |
commit | c3984569c06dc3c2890516e95adc38dcab9ec89a (patch) | |
tree | c3b134eb11cadad6b70ff866e4c9e1167b509235 | |
parent | 34d872628d5099ae520dd92433e211f561aaf611 (diff) | |
download | minetest-c3984569c06dc3c2890516e95adc38dcab9ec89a.tar.gz minetest-c3984569c06dc3c2890516e95adc38dcab9ec89a.tar.bz2 minetest-c3984569c06dc3c2890516e95adc38dcab9ec89a.zip |
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
27 files changed, 3514 insertions, 2496 deletions
diff --git a/builtin/mainmenu/filterlist.lua b/builtin/common/filterlist.lua index 379a5cea9..99c4bca1c 100644 --- a/builtin/mainmenu/filterlist.lua +++ b/builtin/common/filterlist.lua @@ -16,6 +16,8 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- +-- TODO improve doc -- +-- TODO code cleanup -- -- Generic implementation of a filter/sortable list -- -- Usage: -- -- 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_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) return this diff --git a/builtin/fstk/buttonbar.lua b/builtin/fstk/buttonbar.lua new file mode 100644 index 000000000..f5ac8905e --- /dev/null +++ b/builtin/fstk/buttonbar.lua @@ -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 diff --git a/builtin/fstk/dialog.lua b/builtin/fstk/dialog.lua new file mode 100644 index 000000000..214b0388f --- /dev/null +++ b/builtin/fstk/dialog.lua @@ -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 diff --git a/builtin/fstk/tabview.lua b/builtin/fstk/tabview.lua new file mode 100644 index 000000000..47603fb1b --- /dev/null +++ b/builtin/fstk/tabview.lua @@ -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 diff --git a/builtin/fstk/ui.lua b/builtin/fstk/ui.lua new file mode 100644 index 000000000..e0438247c --- /dev/null +++ b/builtin/fstk/ui.lua @@ -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 diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua new file mode 100644 index 000000000..c555ec92f --- /dev/null +++ b/builtin/mainmenu/common.lua @@ -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 diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua new file mode 100644 index 000000000..a459f0ff1 --- /dev/null +++ b/builtin/mainmenu/dlg_config_world.lua @@ -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 diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua new file mode 100644 index 000000000..5d18bfd22 --- /dev/null +++ b/builtin/mainmenu/dlg_create_world.lua @@ -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 diff --git a/builtin/mainmenu/dlg_delete_mod.lua b/builtin/mainmenu/dlg_delete_mod.lua new file mode 100644 index 000000000..6e00b8045 --- /dev/null +++ b/builtin/mainmenu/dlg_delete_mod.lua @@ -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 diff --git a/builtin/mainmenu/dlg_delete_world.lua b/builtin/mainmenu/dlg_delete_world.lua new file mode 100644 index 000000000..e979bd555 --- /dev/null +++ b/builtin/mainmenu/dlg_delete_world.lua @@ -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 diff --git a/builtin/mainmenu/dlg_rename_modpack.lua b/builtin/mainmenu/dlg_rename_modpack.lua new file mode 100644 index 000000000..9e252408a --- /dev/null +++ b/builtin/mainmenu/dlg_rename_modpack.lua @@ -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 diff --git a/builtin/mainmenu/gamemgr.lua b/builtin/mainmenu/gamemgr.lua index c99c2de21..64fb41b9d 100644 --- a/builtin/mainmenu/gamemgr.lua +++ b/builtin/mainmenu/gamemgr.lua @@ -18,145 +18,8 @@ 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) - for i=1,#gamemgr.games,1 do + for i=1,#gamemgr.games,1 do if gamemgr.games[i].id == gameid then return gamemgr.games[i], i end @@ -183,129 +46,22 @@ function gamemgr.get_game_modlist(gamespec) retval = retval.."," end retval = retval .. game_mods[i].name - end - return retval -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 return gamemgr.games[index] end - + return nil end -------------------------------------------------------------------------------- function gamemgr.update_gamelist() - gamemgr.games = engine.get_games() + gamemgr.games = core.get_games() end -------------------------------------------------------------------------------- @@ -313,10 +69,15 @@ function gamemgr.gamelist() local retval = "" if #gamemgr.games > 0 then retval = retval .. gamemgr.games[1].id - + for i=2,#gamemgr.games,1 do retval = retval .. "," .. gamemgr.games[i].name end end return retval end + +-------------------------------------------------------------------------------- +-- read initial data +-------------------------------------------------------------------------------- +gamemgr.update_gamelist() diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 58e9ab949..ab2b8d80c 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -1,147 +1,71 @@ - -engine = core -local menupath = core.get_mainmenu_path()..DIR_DELIM -local commonpath = core.get_builtin_path()..DIR_DELIM.."common"..DIR_DELIM - -dofile(menupath.."filterlist.lua") -dofile(menupath.."modmgr.lua") -dofile(menupath.."modstore.lua") -dofile(menupath.."gamemgr.lua") -dofile(menupath.."textures.lua") -dofile(menupath.."menubar.lua") -dofile(commonpath.."async_event.lua") +--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. mt_color_grey = "#AAAAAA" mt_color_blue = "#0000DD" mt_color_green = "#00DD00" mt_color_dark_green = "#003300" ---for all other colors ask sfan5 to complete his worK! - -menu = {} -local tabbuilder = {} -local worldlist = nil - --------------------------------------------------------------------------------- -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 - --------------------------------------------------------------------------------- -function menu.render_favorite(spec,render_details) - local text = "" - - if spec.name ~= nil then - text = text .. engine.formspec_escape(spec.name:trim()) - --- if spec.description ~= nil and --- engine.formspec_escape(spec.description):trim() ~= "" then --- text = text .. " (" .. engine.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 +--for all other colors ask sfan5 to complete his work! - return playercount .. engine.formspec_escape(details) .. text -end - --------------------------------------------------------------------------------- -os.tempfolder = function() - 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 +local menupath = core.get_mainmenu_path() +local basepath = core.get_builtin_path() +defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" .. + DIR_DELIM .. "pack" .. DIR_DELIM --------------------------------------------------------------------------------- -function text2textlist(xpos,ypos,width,height,tl_name,textlen,text,transparency) - local textlines = engine.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 .. engine.formspec_escape(textlines[i]) .. "," - end - - retval = retval .. ";0;" - - if transparency then - retval = retval .. "true" +dofile(basepath .. DIR_DELIM .. "common" .. DIR_DELIM .. "async_event.lua") +dofile(basepath .. DIR_DELIM .. "common" .. DIR_DELIM .. "filterlist.lua") +dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "buttonbar.lua") +dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "dialog.lua") +dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "tabview.lua") +dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "ui.lua") +dofile(menupath .. DIR_DELIM .. "common.lua") +dofile(menupath .. DIR_DELIM .. "gamemgr.lua") +dofile(menupath .. DIR_DELIM .. "modmgr.lua") +dofile(menupath .. DIR_DELIM .. "store.lua") +dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_delete_mod.lua") +dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua") +dofile(menupath .. DIR_DELIM .. "tab_credits.lua") +dofile(menupath .. DIR_DELIM .. "tab_mods.lua") +dofile(menupath .. DIR_DELIM .. "tab_multiplayer.lua") +dofile(menupath .. DIR_DELIM .. "tab_server.lua") +dofile(menupath .. DIR_DELIM .. "tab_settings.lua") +dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua") +dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua") +dofile(menupath .. DIR_DELIM .. "textures.lua") + +-------------------------------------------------------------------------------- +local function main_event_handler(tabview,event) + if event == "MenuQuit" then + core.close() end - - retval = retval .. "]" - - return retval + return true end -------------------------------------------------------------------------------- -function init_globals() +local function init_globals() --init gamedata gamedata.worldindex = 0 - worldlist = filterlist.create( - engine.get_worlds, + menudata.worldlist = filterlist.create( + core.get_worlds, compare_worlds, function(element,uid) if element.name == uid then @@ -157,1182 +81,34 @@ function init_globals() end --filter fct ) - filterlist.add_sort_mechanism(worldlist,"alphabetic",sort_worlds_alphabetic) - filterlist.set_sortmode(worldlist,"alphabetic") -end - --------------------------------------------------------------------------------- -function update_menu() - - local formspec - - -- handle errors - if gamedata.errormessage ~= nil then - formspec = "size[12,5.2,true]" .. - "textarea[1,2;10,2;;ERROR: " .. - engine.formspec_escape(gamedata.errormessage) .. - ";]".. - "button[4.5,4.2;3,0.5;btn_error_confirm;" .. fgettext("Ok") .. "]" - else - formspec = tabbuilder.gettab() - end - - engine.update_formspec(formspec) -end - --------------------------------------------------------------------------------- -function menu.render_world_list() - local retval = "" - - local current_worldlist = filterlist.get_list(worldlist) - - for i,v in ipairs(current_worldlist) do - if retval ~= "" then - retval = retval .."," - end - - retval = retval .. engine.formspec_escape(v.name) .. - " \\[" .. engine.formspec_escape(v.gameid) .. "\\]" - end - - return retval -end - --------------------------------------------------------------------------------- -function menu.render_texture_pack_list(list) - local retval = "" - - for i, v in ipairs(list) do - if retval ~= "" then - retval = retval .."," - end - - retval = retval .. engine.formspec_escape(v) - end - - return retval -end - --------------------------------------------------------------------------------- -function menu.asyncOnlineFavourites() - menu.favorites = {} - engine.handle_async( - function(param) - --return core.get_favorites("online") - end, - nil, - function(result) - menu.favorites = result - engine.event_handler("Refresh") - end - ) -end - --------------------------------------------------------------------------------- -function menu.init() - --init menu data - gamemgr.update_gamelist() - - menu.last_game = tonumber(engine.setting_get("main_menu_last_game_idx")) - - if type(menu.last_game) ~= "number" then - menu.last_game = 1 - end - - if engine.setting_getbool("public_serverlist") then - menu.asyncOnlineFavourites() - else - menu.favorites = engine.get_favorites("local") - end - - menu.defaulttexturedir = engine.get_texturepath_share() .. DIR_DELIM .. "base" .. - DIR_DELIM .. "pack" .. DIR_DELIM -end - --------------------------------------------------------------------------------- -function menu.lastgame() - if menu.last_game > 0 and menu.last_game <= #gamemgr.games then - return gamemgr.games[menu.last_game] - end - - if #gamemgr.games >= 1 then - menu.last_game = 1 - return gamemgr.games[menu.last_game] - end - - --error case!! - return nil -end - --------------------------------------------------------------------------------- -function menu.update_last_game() - - local current_world = filterlist.get_raw_element(worldlist, - engine.setting_get("mainmenu_last_selected_world") - ) - - if current_world == nil then - return - end - - local gamespec, i = gamemgr.find_by_gameid(current_world.gameid) - if i ~= nil then - menu.last_game = i - engine.setting_set("main_menu_last_game_idx",menu.last_game) - end -end - --------------------------------------------------------------------------------- -function menu.handle_key_up_down(fields,textlist,settingname) - - if fields["key_up"] then - local oldidx = engine.get_textlist_index(textlist) - - if oldidx ~= nil and oldidx > 1 then - local newidx = oldidx -1 - engine.setting_set(settingname, - filterlist.get_raw_index(worldlist,newidx)) - end - end - - if fields["key_down"] then - local oldidx = engine.get_textlist_index(textlist) - - if oldidx ~= nil and oldidx < filterlist.size(worldlist) then - local newidx = oldidx + 1 - engine.setting_set(settingname, - filterlist.get_raw_index(worldlist,newidx)) - end - end -end - --------------------------------------------------------------------------------- -function tabbuilder.dialog_create_world() - local mapgens = {"v6", "v7", "indev", "singlenode", "math"} - - local current_seed = engine.setting_get("fixed_map_seed") or "" - local current_mg = engine.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 retval = - "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() .. - ";" .. menu.last_game .. ";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 - --------------------------------------------------------------------------------- -function tabbuilder.dialog_delete_world() - return "label[2,2;" .. - fgettext("Delete World \"$1\"?", filterlist.get_raw_list(worldlist)[menu.world_to_del].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") .. "]" -end - --------------------------------------------------------------------------------- - -function tabbuilder.gettab() - local tsize = tabbuilder.tabsizes[tabbuilder.current_tab] or {width=12, height=5.2} - local retval = "size[" .. tsize.width .. "," .. tsize.height .. ",true]" - - if tabbuilder.show_buttons then - retval = retval .. tabbuilder.tab_header() - end - - local buildfunc = tabbuilder.tabfuncs[tabbuilder.current_tab] - if buildfunc ~= nil then - retval = retval .. buildfunc() - end - - retval = retval .. modmgr.gettab(tabbuilder.current_tab) - retval = retval .. gamemgr.gettab(tabbuilder.current_tab) - retval = retval .. modstore.gettab(tabbuilder.current_tab) - - return retval -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_create_world_buttons(fields) - - if fields["world_create_confirm"] or - fields["key_enter"] then - - local worldname = fields["te_world_name"] - local gameindex = engine.get_textlist_index("games") - - if gameindex ~= nil and - worldname ~= "" then - - local message = nil - - if not filterlist.uid_exists_raw(worldlist,worldname) then - engine.setting_set("mg_name",fields["dd_mapgen"]) - message = engine.create_world(worldname,gameindex) - else - message = fgettext("A world named \"$1\" already exists", worldname) - end - - engine.setting_set("fixed_map_seed", fields["te_seed"]) - - if message ~= nil then - gamedata.errormessage = message - else - menu.last_game = gameindex - engine.setting_set("main_menu_last_game_idx",gameindex) - - filterlist.refresh(worldlist) - engine.setting_set("mainmenu_last_selected_world", - filterlist.raw_index_by_uid(worldlist,worldname)) - end - else - gamedata.errormessage = - fgettext("No worldname given or no game selected") - end - end - - if fields["games"] then - tabbuilder.skipformupdate = true - return - end - - --close dialog - tabbuilder.is_dialog = false - tabbuilder.show_buttons = true - tabbuilder.current_tab = engine.setting_get("main_menu_tab") -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_delete_world_buttons(fields) - - if fields["world_delete_confirm"] then - if menu.world_to_del > 0 and - menu.world_to_del <= #filterlist.get_raw_list(worldlist) then - engine.delete_world(menu.world_to_del) - menu.world_to_del = 0 - filterlist.refresh(worldlist) - end - end - - tabbuilder.is_dialog = false - tabbuilder.show_buttons = true - tabbuilder.current_tab = engine.setting_get("main_menu_tab") -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_multiplayer_buttons(fields) - - if fields["te_name"] ~= nil then - gamedata.playername = fields["te_name"] - engine.setting_set("name", fields["te_name"]) - end - - if fields["favourites"] ~= nil then - local event = engine.explode_textlist_event(fields["favourites"]) - if event.type == "DCL" then - if event.index <= #menu.favorites then - gamedata.address = menu.favorites[event.index].address - gamedata.port = menu.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 menu.favorites ~= nil then - gamedata.servername = menu.favorites[event.index].name - gamedata.serverdescription = menu.favorites[event.index].description - end - - if gamedata.address ~= nil and - gamedata.port ~= nil then - engine.setting_set("address",gamedata.address) - engine.setting_set("remote_port",gamedata.port) - engine.start() - end - end - end - - if event.type == "CHG" then - if event.index <= #menu.favorites then - local address = menu.favorites[event.index].address - local port = menu.favorites[event.index].port - - if address ~= nil and - port ~= nil then - engine.setting_set("address",address) - engine.setting_set("remote_port",port) - end - - menu.fav_selected = event.index - end - end - return - end - - if fields["key_up"] ~= nil or - fields["key_down"] ~= nil then - - local fav_idx = engine.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 < #menu.favorites then - fav_idx = fav_idx +1 - end end - end - - local address = menu.favorites[fav_idx].address - local port = menu.favorites[fav_idx].port - - if address ~= nil and - port ~= nil then - engine.setting_set("address",address) - engine.setting_set("remote_port",port) - end - - menu.fav_selected = fav_idx - return - end - - if fields["cb_public_serverlist"] ~= nil then - engine.setting_set("public_serverlist", fields["cb_public_serverlist"]) - - if engine.setting_getbool("public_serverlist") then - menu.asyncOnlineFavourites() - else - menu.favorites = engine.get_favorites("local") - end - menu.fav_selected = nil - return - end - - if fields["btn_delete_favorite"] ~= nil then - local current_favourite = engine.get_textlist_index("favourites") - if current_favourite == nil then return end - engine.delete_favorite(current_favourite) - menu.favorites = engine.get_favorites() - menu.fav_selected = nil - - engine.setting_set("address","") - engine.setting_set("remote_port","30000") - - return - 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 = engine.get_textlist_index("favourites") - - if fav_idx ~= nil and fav_idx <= #menu.favorites and - menu.favorites[fav_idx].address == fields["te_address"] and - menu.favorites[fav_idx].port == fields["te_port"] then - - gamedata.servername = menu.favorites[fav_idx].name - gamedata.serverdescription = menu.favorites[fav_idx].description - else - gamedata.servername = "" - gamedata.serverdescription = "" - end - - gamedata.selected_world = 0 - - engine.setting_set("address",fields["te_address"]) - engine.setting_set("remote_port",fields["te_port"]) - - engine.start() - return - end -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_server_buttons(fields) - - local world_doubleclick = false - - if fields["srv_worlds"] ~= nil then - local event = engine.explode_textlist_event(fields["srv_worlds"]) - - if event.type == "DCL" then - world_doubleclick = true - end - if event.type == "CHG" then - engine.setting_set("mainmenu_last_selected_world", - filterlist.get_raw_index(worldlist,engine.get_textlist_index("srv_worlds"))) - end - end - - menu.handle_key_up_down(fields,"srv_worlds","mainmenu_last_selected_world") - - if fields["cb_creative_mode"] then - engine.setting_set("creative_mode", fields["cb_creative_mode"]) - end - - if fields["cb_enable_damage"] then - engine.setting_set("enable_damage", fields["cb_enable_damage"]) - end - - if fields["cb_server_announce"] then - engine.setting_set("server_announce", fields["cb_server_announce"]) - end - - if fields["start_server"] ~= nil or - world_doubleclick or - fields["key_enter"] then - local selected = engine.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 = filterlist.get_raw_index(worldlist,selected) - - engine.setting_set("port",gamedata.port) - if fields["te_serveraddr"] ~= nil then - engine.setting_set("bind_address",fields["te_serveraddr"]) - end - - menu.update_last_game(gamedata.selected_world) - engine.start() - end - end - - if fields["world_create"] ~= nil then - tabbuilder.current_tab = "dialog_create_world" - tabbuilder.is_dialog = true - tabbuilder.show_buttons = false - end - - if fields["world_delete"] ~= nil then - local selected = engine.get_textlist_index("srv_worlds") - if selected ~= nil and - selected <= filterlist.size(worldlist) then - local world = filterlist.get_list(worldlist)[selected] - if world ~= nil and - world.name ~= nil and - world.name ~= "" then - menu.world_to_del = filterlist.get_raw_index(worldlist,selected) - tabbuilder.current_tab = "dialog_delete_world" - tabbuilder.is_dialog = true - tabbuilder.show_buttons = false - else - menu.world_to_del = 0 - end - end - end - - if fields["world_configure"] ~= nil then - selected = engine.get_textlist_index("srv_worlds") - if selected ~= nil then - modmgr.world_config_selected_world = filterlist.get_raw_index(worldlist,selected) - if modmgr.init_worldconfig() then - tabbuilder.current_tab = "dialog_configure_world" - tabbuilder.is_dialog = true - tabbuilder.show_buttons = false - end - end - end -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_settings_buttons(fields) - if fields["cb_fancy_trees"] then - engine.setting_set("new_style_leaves", fields["cb_fancy_trees"]) - end - if fields["cb_smooth_lighting"] then - engine.setting_set("smooth_lighting", fields["cb_smooth_lighting"]) - end - if fields["cb_3d_clouds"] then - engine.setting_set("enable_3d_clouds", fields["cb_3d_clouds"]) - end - if fields["cb_opaque_water"] then - engine.setting_set("opaque_water", fields["cb_opaque_water"]) - end - - if fields["cb_mipmapping"] then - engine.setting_set("mip_map", fields["cb_mipmapping"]) - end - if fields["cb_anisotrophic"] then - engine.setting_set("anisotropic_filter", fields["cb_anisotrophic"]) - end - if fields["cb_bilinear"] then - engine.setting_set("bilinear_filter", fields["cb_bilinear"]) - end - if fields["cb_trilinear"] then - engine.setting_set("trilinear_filter", fields["cb_trilinear"]) - end - - if fields["cb_shaders"] then - if (engine.setting_get("video_driver") == "direct3d8" or engine.setting_get("video_driver") == "direct3d9") then - engine.setting_set("enable_shaders", "false") - gamedata.errormessage = fgettext("To enable shaders the OpenGL driver needs to be used.") - else - engine.setting_set("enable_shaders", fields["cb_shaders"]) - end - end - if fields["cb_pre_ivis"] then - engine.setting_set("preload_item_visuals", fields["cb_pre_ivis"]) - end - if fields["cb_particles"] then - engine.setting_set("enable_particles", fields["cb_particles"]) - end - if fields["cb_bumpmapping"] then - engine.setting_set("enable_bumpmapping", fields["cb_bumpmapping"]) - end - if fields["cb_parallax"] then - engine.setting_set("enable_parallax_occlusion", fields["cb_parallax"]) - end - if fields["cb_generate_normalmaps"] then - engine.setting_set("generate_normalmaps", fields["cb_generate_normalmaps"]) - end - if fields["cb_waving_water"] then - engine.setting_set("enable_waving_water", fields["cb_waving_water"]) - end - if fields["cb_waving_leaves"] then - engine.setting_set("enable_waving_leaves", fields["cb_waving_leaves"]) - end - if fields["cb_waving_plants"] then - engine.setting_set("enable_waving_plants", fields["cb_waving_plants"]) - end - if fields["btn_change_keys"] ~= nil then - engine.show_keys_menu() - end -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_singleplayer_buttons(fields) - - local world_doubleclick = false - - if fields["sp_worlds"] ~= nil then - local event = engine.explode_textlist_event(fields["sp_worlds"]) - - if event.type == "DCL" then - world_doubleclick = true - end - - if event.type == "CHG" then - engine.setting_set("mainmenu_last_selected_world", - filterlist.get_raw_index(worldlist,engine.get_textlist_index("sp_worlds"))) - end - end - - menu.handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world") - - if fields["cb_creative_mode"] then - engine.setting_set("creative_mode", fields["cb_creative_mode"]) - end - - if fields["cb_enable_damage"] then - engine.setting_set("enable_damage", fields["cb_enable_damage"]) - end - - if fields["play"] ~= nil or - world_doubleclick or - fields["key_enter"] then - local selected = engine.get_textlist_index("sp_worlds") - if selected ~= nil then - gamedata.selected_world = filterlist.get_raw_index(worldlist,selected) - gamedata.singleplayer = true - - menu.update_last_game(gamedata.selected_world) - - engine.start() - end - end - - if fields["world_create"] ~= nil then - tabbuilder.current_tab = "dialog_create_world" - tabbuilder.is_dialog = true - tabbuilder.show_buttons = false - end - - if fields["world_delete"] ~= nil then - local selected = engine.get_textlist_index("sp_worlds") - if selected ~= nil and - selected <= filterlist.size(worldlist) then - local world = filterlist.get_list(worldlist)[selected] - if world ~= nil and - world.name ~= nil and - world.name ~= "" then - menu.world_to_del = filterlist.get_raw_index(worldlist,selected) - tabbuilder.current_tab = "dialog_delete_world" - tabbuilder.is_dialog = true - tabbuilder.show_buttons = false - else - menu.world_to_del = 0 - end - end - end - - if fields["world_configure"] ~= nil then - selected = engine.get_textlist_index("sp_worlds") - if selected ~= nil then - modmgr.world_config_selected_world = filterlist.get_raw_index(worldlist,selected) - if modmgr.init_worldconfig() then - tabbuilder.current_tab = "dialog_configure_world" - tabbuilder.is_dialog = true - tabbuilder.show_buttons = false - end - end - end -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_texture_pack_buttons(fields) - if fields["TPs"] ~= nil then - local event = engine.explode_textlist_event(fields["TPs"]) - if event.type == "CHG" or event.type == "DCL" then - local index = engine.get_textlist_index("TPs") - engine.setting_set("mainmenu_last_selected_TP", - index) - local list = filter_texture_pack_list(engine.get_dirlist(engine.get_texturepath(), true)) - local current_index = engine.get_textlist_index("TPs") - if current_index ~= nil and #list >= current_index then - local new_path = engine.get_texturepath()..DIR_DELIM..list[current_index] - if list[current_index] == "None" then new_path = "" end - - engine.setting_set("texture_path", new_path) - end - end - end -end - --------------------------------------------------------------------------------- -function tabbuilder.tab_header() - - if tabbuilder.last_tab_index == nil then - tabbuilder.last_tab_index = 1 - end - - local toadd = "" - - for i=1,#tabbuilder.current_buttons,1 do - - if toadd ~= "" then - toadd = toadd .. "," - end - - toadd = toadd .. tabbuilder.current_buttons[i].caption - end - return "tabheader[-0.3,-0.99;main_tab;" .. toadd ..";" .. tabbuilder.last_tab_index .. ";true;false]" -end - --------------------------------------------------------------------------------- -function tabbuilder.handle_tab_buttons(fields) - - if fields["main_tab"] then - local index = tonumber(fields["main_tab"]) - tabbuilder.last_tab_index = index - tabbuilder.current_tab = tabbuilder.current_buttons[index].name - - engine.setting_set("main_menu_tab",tabbuilder.current_tab) - end - - --handle tab changes - if tabbuilder.current_tab ~= tabbuilder.old_tab then - if tabbuilder.current_tab ~= "singleplayer" and not tabbuilder.is_dialog then - menu.update_gametype(true) - end - end - - if tabbuilder.current_tab == "singleplayer" then - menu.update_gametype() - end - - tabbuilder.old_tab = tabbuilder.current_tab -end - --------------------------------------------------------------------------------- -function tabbuilder.tab_multiplayer() - - 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;;" ..engine.setting_get("address") .."]" .. - "field[6.75,5.25;2.25,0.5;te_port;;" ..engine.setting_get("remote_port") .."]" .. - "checkbox[1,3.6;cb_public_serverlist;".. fgettext("Public Serverlist") .. ";" .. - dump(engine.setting_getbool("public_serverlist")) .. "]" - - if not engine.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;;" ..engine.setting_get("name") .."]" .. - "pwdfield[9.3,4.5;2.5,0.5;te_pwd;]" .. - "textarea[9.3,0.25;2.5,2.75;;" - if menu.fav_selected ~= nil and - menu.favorites[menu.fav_selected].description ~= nil then - retval = retval .. - engine.formspec_escape(menu.favorites[menu.fav_selected].description,true) - end - - retval = retval .. - ";]" .. - "textlist[1,0.35;7.5,3.35;favourites;" - - local render_details = engine.setting_getbool("public_serverlist") - - if #menu.favorites > 0 then - retval = retval .. menu.render_favorite(menu.favorites[1],render_details) - - for i=2,#menu.favorites,1 do - retval = retval .. "," .. menu.render_favorite(menu.favorites[i],render_details) - end - end - - if menu.fav_selected ~= nil then - retval = retval .. ";" .. menu.fav_selected .. "]" - else - retval = retval .. ";0]" - end - - return retval -end - --------------------------------------------------------------------------------- -function tabbuilder.tab_server() - - local index = filterlist.get_current_index(worldlist, - tonumber(engine.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(engine.setting_getbool("creative_mode")) .. "]".. - "checkbox[0.5,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. - dump(engine.setting_getbool("enable_damage")) .. "]".. - "checkbox[0.5,1.15;cb_server_announce;".. fgettext("Public") .. ";" .. - dump(engine.setting_getbool("server_announce")) .. "]".. - "field[0.8,3.2;3.5,0.5;te_playername;".. fgettext("Name") .. ";" .. - engine.setting_get("name") .. "]" .. - "pwdfield[0.8,4.2;3.5,0.5;te_passwd;".. fgettext("Password") .. "]" - - local bind_addr = engine.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") .. ";" .. - engine.setting_get("bind_address") .."]" .. - "field[3.05,5.2;1.25,0.5;te_serverport;".. fgettext("Port") .. ";" .. - engine.setting_get("port") .."]" - else - retval = retval .. - "field[0.8,5.2;3.5,0.5;te_serverport;".. fgettext("Server Port") .. ";" .. - engine.setting_get("port") .."]" - end + menudata.worldlist:add_sort_mechanism("alphabetic",sort_worlds_alphabetic) + menudata.worldlist:set_sortmode("alphabetic") - retval = retval .. - "textlist[4,0.25;7.5,3.7;srv_worlds;" .. - menu.render_world_list() .. - ";" .. index .. "]" - - return retval -end - --------------------------------------------------------------------------------- -function tabbuilder.tab_settings() - tab_string = - "vertlabel[0,0;" .. fgettext("SETTINGS") .. "]" .. - "checkbox[1,0;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";" - .. dump(engine.setting_getbool("new_style_leaves")) .. "]".. - "checkbox[1,0.5;cb_smooth_lighting;".. fgettext("Smooth Lighting") - .. ";".. dump(engine.setting_getbool("smooth_lighting")) .. "]".. - "checkbox[1,1;cb_3d_clouds;".. fgettext("3D Clouds") .. ";" - .. dump(engine.setting_getbool("enable_3d_clouds")) .. "]".. - "checkbox[1,1.5;cb_opaque_water;".. fgettext("Opaque Water") .. ";" - .. dump(engine.setting_getbool("opaque_water")) .. "]".. - "checkbox[1,2.0;cb_pre_ivis;".. fgettext("Preload item visuals") .. ";" - .. dump(engine.setting_getbool("preload_item_visuals")) .. "]".. - "checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";" - .. dump(engine.setting_getbool("enable_particles")) .. "]".. - "checkbox[4.5,0;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";" - .. dump(engine.setting_getbool("mip_map")) .. "]".. - "checkbox[4.5,0.5;cb_anisotrophic;".. fgettext("Anisotropic Filtering") .. ";" - .. dump(engine.setting_getbool("anisotropic_filter")) .. "]".. - "checkbox[4.5,1.0;cb_bilinear;".. fgettext("Bi-Linear Filtering") .. ";" - .. dump(engine.setting_getbool("bilinear_filter")) .. "]".. - "checkbox[4.5,1.5;cb_trilinear;".. fgettext("Tri-Linear Filtering") .. ";" - .. dump(engine.setting_getbool("trilinear_filter")) .. "]".. - - "checkbox[8,0;cb_shaders;".. fgettext("Shaders") .. ";" - .. dump(engine.setting_getbool("enable_shaders")) .. "]".. - "button[1,4.5;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]" - - if engine.setting_getbool("enable_shaders") then - tab_string = tab_string .. - "checkbox[8,0.5;cb_bumpmapping;".. fgettext("Bumpmapping") .. ";" - .. dump(engine.setting_getbool("enable_bumpmapping")) .. "]".. - "checkbox[8,1.0;cb_parallax;".. fgettext("Parallax Occlusion") .. ";" - .. dump(engine.setting_getbool("enable_parallax_occlusion")) .. "]".. - "checkbox[8,1.5;cb_generate_normalmaps;".. fgettext("Generate Normalmaps") .. ";" - .. dump(engine.setting_getbool("generate_normalmaps")) .. "]".. - "checkbox[8,2.0;cb_waving_water;".. fgettext("Waving Water") .. ";" - .. dump(engine.setting_getbool("enable_waving_water")) .. "]".. - "checkbox[8,2.5;cb_waving_leaves;".. fgettext("Waving Leaves") .. ";" - .. dump(engine.setting_getbool("enable_waving_leaves")) .. "]".. - "checkbox[8,3.0;cb_waving_plants;".. fgettext("Waving Plants") .. ";" - .. dump(engine.setting_getbool("enable_waving_plants")) .. "]" - else - tab_string = tab_string .. - "textlist[8.33,0.7;4,1;;#888888" .. fgettext("Bumpmapping") .. ";0;true]" .. - "textlist[8.33,1.2;4,1;;#888888" .. fgettext("Parallax Occlusion") .. ";0;true]" .. - "textlist[8.33,1.7;4,1;;#888888" .. fgettext("Generate Normalmaps") .. ";0;true]" .. - "textlist[8.33,2.2;4,1;;#888888" .. fgettext("Waving Water") .. ";0;true]" .. - "textlist[8.33,2.7;4,1;;#888888" .. fgettext("Waving Leaves") .. ";0;true]" .. - "textlist[8.33,3.2;4,1;;#888888" .. fgettext("Waving Plants") .. ";0;true]" - end - return tab_string -end - --------------------------------------------------------------------------------- -function tabbuilder.tab_singleplayer() - - local index = filterlist.get_current_index(worldlist, - tonumber(engine.setting_get("mainmenu_last_selected_world")) - ) - - return "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(engine.setting_getbool("creative_mode")) .. "]".. - "checkbox[0.5,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. - dump(engine.setting_getbool("enable_damage")) .. "]".. - "textlist[4,0.25;7.5,3.7;sp_worlds;" .. - menu.render_world_list() .. - ";" .. index .. "]" .. - menubar.formspec -end - --------------------------------------------------------------------------------- -function tabbuilder.tab_texture_packs() - 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 = engine.setting_get("texture_path") - local list = filter_texture_pack_list(engine.get_dirlist(engine.get_texturepath(), true)) - local index = tonumber(engine.setting_get("mainmenu_last_selected_TP")) - - if index == nil then index = 1 end - - if current_texture_path == "" then - retval = retval .. - menu.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 = menu.defaulttexturedir .. "no_screenshot.png" - end - - return retval .. - menu.render_texture_pack_list(list) .. - ";" .. index .. "]" .. - "image[0.65,0.25;4.0,3.7;"..engine.formspec_escape(screenfile or no_screenshot).."]".. - "textarea[1.0,3.25;3.7,1.5;;"..engine.formspec_escape(infotext or "")..";]" -end - --------------------------------------------------------------------------------- -function tabbuilder.tab_credits() - local logofile = menu.defaulttexturedir .. "logo.png" - return "vertlabel[0,-0.5;CREDITS]" .. - "label[0.5,3;Minetest " .. engine.get_version() .. "]" .. - "label[0.5,3.3;http://minetest.net]" .. - "image[0.5,1;" .. engine.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 - --------------------------------------------------------------------------------- -function tabbuilder.init() - tabbuilder.tabfuncs = { - singleplayer = tabbuilder.tab_singleplayer, - multiplayer = tabbuilder.tab_multiplayer, - server = tabbuilder.tab_server, - settings = tabbuilder.tab_settings, - texture_packs = tabbuilder.tab_texture_packs, - credits = tabbuilder.tab_credits, - dialog_create_world = tabbuilder.dialog_create_world, - dialog_delete_world = tabbuilder.dialog_delete_world - } - - tabbuilder.tabsizes = { - dialog_create_world = {width=12, height=7}, - dialog_delete_world = {width=12, height=5.2} - } - - tabbuilder.current_tab = engine.setting_get("main_menu_tab") - - if tabbuilder.current_tab == nil or - tabbuilder.current_tab == "" then - tabbuilder.current_tab = "singleplayer" - engine.setting_set("main_menu_tab",tabbuilder.current_tab) - end - - --initialize tab buttons - tabbuilder.last_tab = nil - tabbuilder.show_buttons = true - - tabbuilder.current_buttons = {} - table.insert(tabbuilder.current_buttons,{name="singleplayer", caption=fgettext("Singleplayer")}) - table.insert(tabbuilder.current_buttons,{name="multiplayer", caption=fgettext("Client")}) - table.insert(tabbuilder.current_buttons,{name="server", caption=fgettext("Server")}) - table.insert(tabbuilder.current_buttons,{name="settings", caption=fgettext("Settings")}) - table.insert(tabbuilder.current_buttons,{name="texture_packs", caption=fgettext("Texture Packs")}) - - if engine.setting_getbool("main_menu_game_mgr") then - table.insert(tabbuilder.current_buttons,{name="game_mgr", caption=fgettext("Games")}) - end - - if engine.setting_getbool("main_menu_mod_mgr") then - table.insert(tabbuilder.current_buttons,{name="mod_mgr", caption=fgettext("Mods")}) - end - table.insert(tabbuilder.current_buttons,{name="credits", caption=fgettext("Credits")}) - - - for i=1,#tabbuilder.current_buttons,1 do - if tabbuilder.current_buttons[i].name == tabbuilder.current_tab then - tabbuilder.last_tab_index = i - end - end - - if tabbuilder.current_tab ~= "singleplayer" then - menu.update_gametype(true) - else - menu.update_gametype() - end -end - --------------------------------------------------------------------------------- -function tabbuilder.checkretval(retval) - - if retval ~= nil then - if retval.current_tab ~= nil then - tabbuilder.current_tab = retval.current_tab - end - - if retval.is_dialog ~= nil then - tabbuilder.is_dialog = retval.is_dialog - end - - if retval.show_buttons ~= nil then - tabbuilder.show_buttons = retval.show_buttons - end - - if retval.skipformupdate ~= nil then - tabbuilder.skipformupdate = retval.skipformupdate - end - - if retval.ignore_menu_quit == true then - tabbuilder.ignore_menu_quit = true - else - tabbuilder.ignore_menu_quit = false - end - end -end - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- initialize callbacks --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -engine.button_handler = function(fields) - --print("Buttonhandler: tab: " .. tabbuilder.current_tab .. " fields: " .. dump(fields)) - - if fields["btn_error_confirm"] then - gamedata.errormessage = nil - end - - local retval = modmgr.handle_buttons(tabbuilder.current_tab,fields) - tabbuilder.checkretval(retval) - - retval = gamemgr.handle_buttons(tabbuilder.current_tab,fields) - tabbuilder.checkretval(retval) - - retval = modstore.handle_buttons(tabbuilder.current_tab,fields) - tabbuilder.checkretval(retval) - - if tabbuilder.current_tab == "dialog_create_world" then - tabbuilder.handle_create_world_buttons(fields) - end - - if tabbuilder.current_tab == "dialog_delete_world" then - tabbuilder.handle_delete_world_buttons(fields) - end - - if tabbuilder.current_tab == "singleplayer" then - tabbuilder.handle_singleplayer_buttons(fields) - end - - if tabbuilder.current_tab == "texture_packs" then - tabbuilder.handle_texture_pack_buttons(fields) - end - - if tabbuilder.current_tab == "multiplayer" then - tabbuilder.handle_multiplayer_buttons(fields) - end - - if tabbuilder.current_tab == "settings" then - tabbuilder.handle_settings_buttons(fields) - end - - if tabbuilder.current_tab == "server" then - tabbuilder.handle_server_buttons(fields) - end - - --tab buttons - tabbuilder.handle_tab_buttons(fields) - - --menubar buttons - menubar.handle_buttons(fields) - - if not tabbuilder.skipformupdate then - --update menu - update_menu() - else - tabbuilder.skipformupdate = false - end -end - --------------------------------------------------------------------------------- -engine.event_handler = function(event) - if event == "MenuQuit" then - if tabbuilder.is_dialog then - if tabbuilder.ignore_menu_quit then - return - end - - tabbuilder.is_dialog = false - tabbuilder.show_buttons = true - tabbuilder.current_tab = engine.setting_get("main_menu_tab") - menu.update_gametype() - update_menu() - else - engine.close() - end - end - - if event == "Refresh" then - update_menu() - end -end + mm_texture.init() + + --create main tabview + local tv_main = tabview_create("maintab",{x=12,y=5.2},{x=-0.3,y=-0.99}) + tv_main:set_autosave_tab(true) + tv_main:add(tab_singleplayer) + tv_main:add(tab_multiplayer) + tv_main:add(tab_server) + tv_main:add(tab_settings) + tv_main:add(tab_texturepacks) + tv_main:add(tab_mods) + tv_main:add(tab_credits) + + tv_main:set_global_event_handler(main_event_handler) + + tv_main:set_tab(core.setting_get("maintab_LAST")) + ui.set_default("maintab") + tv_main:show() --------------------------------------------------------------------------------- -function menu.update_gametype(reset) - local game = menu.lastgame() + --create modstore ui + modstore.init({x=12,y=8},4,3) - if reset or game == nil then - mm_texture.reset() - engine.set_topleft_text("") - filterlist.set_filtercriteria(worldlist,nil) - else - mm_texture.update(tabbuilder.current_tab,game) - engine.set_topleft_text(game.name) - filterlist.set_filtercriteria(worldlist,game.id) - end + ui.update() + + core.sound_play("main_menu", true) end --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- menu startup --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- init_globals() -mm_texture.init() -menu.init() -tabbuilder.init() -menubar.refresh() -modstore.init() - -engine.sound_play("main_menu", true) - -update_menu() diff --git a/builtin/mainmenu/menubar.lua b/builtin/mainmenu/menubar.lua deleted file mode 100644 index 2e4d5f8b8..000000000 --- a/builtin/mainmenu/menubar.lua +++ /dev/null @@ -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 diff --git a/builtin/mainmenu/modmgr.lua b/builtin/mainmenu/modmgr.lua index baf61d2a5..dcd1eb256 100644 --- a/builtin/mainmenu/modmgr.lua +++ b/builtin/mainmenu/modmgr.lua @@ -18,16 +18,16 @@ -------------------------------------------------------------------------------- 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 local toadd = {} local modpackfile = nil - toadd.name = mods[i] - toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM + toadd.name = mods[i] + toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM if modpack ~= nil and modpack ~= "" then - toadd.modpack = modpack + toadd.modpack = modpack else local filename = path .. DIR_DELIM .. mods[i] .. DIR_DELIM .. "modpack.txt" local error = nil @@ -55,8 +55,8 @@ function modmgr.extract(modfile) if tempfolder ~= nil and tempfolder ~= "" then - engine.create_dir(tempfolder) - if engine.extract_zip(modfile.name,tempfolder) then + core.create_dir(tempfolder) + if core.extract_zip(modfile.name,tempfolder) then return tempfolder end end @@ -92,7 +92,7 @@ function modmgr.getbasefolder(temppath) } end - local subdirs = engine.get_dirlist(temppath,true) + local subdirs = core.get_dirlist(temppath,true) --only single mod or modpack allowed if #subdirs ~= 1 then @@ -193,9 +193,16 @@ function modmgr.identify_modname(modpath,filename) while line~= nil do local modname = nil - if line:find("register_tool") or - line:find("register_craftitem") or - line:find("register_node") then + if line:find("minetest.register_tool") then + modname = modmgr.parse_register_line(line) + 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) end @@ -215,139 +222,6 @@ function modmgr.identify_modname(modpath,filename) return nil 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) local retval = "" @@ -359,7 +233,7 @@ function modmgr.render_modlist(render_list) render_list = modmgr.global_mods end - local list = filterlist.get_list(render_list) + local list = render_list:get_list() local last_modpack = nil for i,v in ipairs(list) do @@ -370,7 +244,7 @@ function modmgr.render_modlist(render_list) local color = "" if v.is_modpack then - local rawlist = filterlist.get_raw_list(render_list) + local rawlist = render_list:get_raw_list() local all_enabled = true for j=1,#rawlist,1 do @@ -407,104 +281,6 @@ function modmgr.render_modlist(render_list) 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) local toadd = "" if modfolder ~= nil then @@ -529,7 +305,6 @@ function modmgr.get_dependencies(modfolder) return toadd end - -------------------------------------------------------------------------------- function modmgr.get_worldconfig(worldpath) local filename = worldpath .. @@ -545,7 +320,7 @@ function modmgr.get_worldconfig(worldpath) if key == "gameid" then worldconfig.id = value else - worldconfig.global_mods[key] = engine.is_yes(value) + worldconfig.global_mods[key] = core.is_yes(value) end end @@ -555,52 +330,6 @@ function modmgr.get_worldconfig(worldpath) return worldconfig 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) @@ -613,7 +342,6 @@ function modmgr.installmod(modfilename,basename) return end - local basefolder = modmgr.getbasefolder(modpath) if basefolder.type == "modpack" then @@ -628,8 +356,8 @@ function modmgr.installmod(modfilename,basename) end if clean_path ~= nil then - local targetpath = engine.get_modpath() .. DIR_DELIM .. clean_path - if not engine.copy_dir(basefolder.path,targetpath) then + local targetpath = core.get_modpath() .. DIR_DELIM .. clean_path + if not core.copy_dir(basefolder.path,targetpath) then gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath) end else @@ -650,235 +378,20 @@ function modmgr.installmod(modfilename,basename) end if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then - local targetpath = engine.get_modpath() .. DIR_DELIM .. targetfolder - engine.copy_dir(basefolder.path,targetpath) + local targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder + core.copy_dir(basefolder.path,targetpath) else gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename) end end - engine.delete_dir(modpath) + core.delete_dir(modpath) modmgr.refresh_globals() 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) local retval = {} @@ -886,7 +399,7 @@ function modmgr.preparemodlist(data) local game_mods = {} --read global mods - local modpath = engine.get_modpath() + local modpath = core.get_modpath() if modpath ~= nil and modpath ~= "" then @@ -922,15 +435,16 @@ function modmgr.preparemodlist(data) key = key:sub(10) local element = nil 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] break end end if element ~= nil then - element.enabled = engine.is_yes(value) + element.enabled = core.is_yes(value) else - engine.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found") + core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found") end end end @@ -939,58 +453,6 @@ function modmgr.preparemodlist(data) 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) if elem1 == nil or elem2 == nil then return false @@ -1016,36 +478,13 @@ function modmgr.comparemod(elem1,elem2) 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) if modmgr.global_mods == nil then modmgr.refresh_globals() 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 end @@ -1059,11 +498,12 @@ function modmgr.get_global_mod(idx) return nil 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 end - return filterlist.get_list(modmgr.global_mods)[idx] + return modmgr.global_mods:get_list()[idx] end -------------------------------------------------------------------------------- @@ -1079,8 +519,8 @@ function modmgr.refresh_globals() nil, --filter {} ) - filterlist.add_sort_mechanism(modmgr.global_mods, "alphabetic", sort_mod_list) - filterlist.set_sortmode(modmgr.global_mods, "alphabetic") + modmgr.global_mods:add_sort_mechanism("alphabetic", sort_mod_list) + modmgr.global_mods:set_sortmode("alphabetic") end -------------------------------------------------------------------------------- diff --git a/builtin/mainmenu/modstore.lua b/builtin/mainmenu/store.lua index ef7fd0165..48433e58d 100644 --- a/builtin/mainmenu/modstore.lua +++ b/builtin/mainmenu/store.lua @@ -22,20 +22,18 @@ modstore = {} -------------------------------------------------------------------------------- -- @function [parent=#modstore] init -function modstore.init() - modstore.tabnames = {} +function modstore.init(size, unsortedmods, searchmods) - table.insert(modstore.tabnames,"dialog_modstore_unsorted") - table.insert(modstore.tabnames,"dialog_modstore_search") + modstore.mods_on_unsorted_page = unsortedmods + modstore.mods_on_search_page = searchmods + modstore.modsperpage = modstore.mods_on_unsorted_page - modstore.modsperpage = 5 - - modstore.basetexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" .. + modstore.basetexturedir = core.get_texturepath() .. DIR_DELIM .. "base" .. DIR_DELIM .. "pack" .. DIR_DELIM modstore.lastmodtitle = "" modstore.last_search = "" - + modstore.searchlist = filterlist.create( function() if modstore.modlist_unsorted ~= nil and @@ -57,18 +55,18 @@ function modstore.init() return false end substring = substring:upper() - + if element.title ~= nil and element.title:upper():find(substring) ~= nil then return true end - + if element.details ~= nil and element.details.author ~= nil and element.details.author:upper():find(substring) ~= nil then return true end - + if element.details ~= nil and element.details.description ~= nil and element.details.description:upper():find(substring) ~= nil then @@ -79,6 +77,31 @@ function modstore.init() ) 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 -------------------------------------------------------------------------------- @@ -95,107 +118,81 @@ function modstore.nametoindex(name) end -------------------------------------------------------------------------------- --- @function [parent=#modstore] getsuccessfuldialog -function modstore.getsuccessfuldialog() - local retval = "" - retval = retval .. "size[6,2,true]" - if modstore.lastmodentry ~= nil then - retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]" - retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]" - - - retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]" - retval = retval .. "label[3,0.75;" .. engine.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]" - - end - retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]" - - - return retval -end +-- @function [parent=#modstore] showdownloading +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 --------------------------------------------------------------------------------- --- @function [parent=#modstore] gettab -function modstore.gettab(tabname) - local retval = "" + this:delete() + return true + end - local is_modstore_tab = false + return false + end, + nil, + modstore.tv_store) - if tabname == "dialog_modstore_unsorted" then - modstore.modsperpage = 5 - retval = modstore.getmodlist(modstore.modlist_unsorted) - is_modstore_tab = true - end + new_dlg.data.title = title + new_dlg:show() +end - if tabname == "dialog_modstore_search" then - retval = modstore.getsearchpage() - is_modstore_tab = true - end +-------------------------------------------------------------------------------- +-- @function [parent=#modstore] successfulldialog +function modstore.successfulldialog() + local new_dlg = dialog_create("store_downloading", + function(data) + local retval = "" + retval = retval .. "size[6,2,true]" + if modstore.lastmodentry ~= nil then + retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]" + retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]" - if is_modstore_tab then - return modstore.tabheader(tabname) .. retval - end - if tabname == "modstore_mod_installed" then - return modstore.getsuccessfuldialog() - end + retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]" + retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]" - if tabname == "modstore_downloading" then - return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") .. - " " .. modstore.lastmodtitle .. " " .. - fgettext("please wait...") .. "]" - end + end + 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 "" -end + return true + 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 false + end, + nil, + modstore.tv_store) - return retval + new_dlg.data.title = title + new_dlg:show() end -------------------------------------------------------------------------------- -- @function [parent=#modstore] handle_buttons -function modstore.handle_buttons(current_tab,fields) - - 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 +function modstore.handle_buttons(parent, fields, name, data) if fields["btn_modstore_page_up"] then if modstore.current_list ~= nil and modstore.current_list.page > 0 then modstore.current_list.page = modstore.current_list.page - 1 end + return true end 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.page +1 end - end - - 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 - } + return true end if fields["btn_modstore_search"] or @@ -243,17 +213,14 @@ function modstore.handle_buttons(current_tab,fields) pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage), data = filterlist.get_list(modstore.searchlist), } + return true end - - + if fields["btn_modstore_close"] then - return { - is_dialog = false, - show_buttons = true, - current_tab = engine.setting_get("main_menu_tab") - } + parent:hide() + return true end - + for key,value in pairs(fields) do local foundat = key:find("btn_install_mod_") if ( foundat == 1) then @@ -265,34 +232,34 @@ function modstore.handle_buttons(current_tab,fields) if modstore.lastmodtitle ~= "" then modstore.lastmodtitle = modstore.lastmodtitle .. ", " end - + modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title - - engine.handle_async( + + if not core.handle_async( function(param) - - local fullurl = engine.setting_get("modstore_download_url") .. + local fullurl = core.setting_get("modstore_download_url") .. param.moddetails.download_url - + if param.version ~= nil then local found = false for i=1,#param.moddetails.versions, 1 do 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 found = true end end - + if not found then + core.log("error","no download url found for version " .. dump(param.version)) return { moddetails = param.moddetails, successfull = false } end end - - if engine.download_file(fullurl,param.filename) then + + if core.download_file(fullurl,param.filename) then return { texturename = param.texturename, moddetails = param.moddetails, @@ -300,6 +267,7 @@ function modstore.handle_buttons(current_tab,fields) successfull = true } else + core.log("error","downloading " .. dump(fullurl) .. " failed") return { moddetails = param.moddetails, successfull = false @@ -313,32 +281,43 @@ function modstore.handle_buttons(current_tab,fields) texturename = modstore.modlist_unsorted.data[i].texturename }, function(result) + print("Result from async: " .. dump(result.successfull)) if result.successfull then modmgr.installmod(result.filename,result.moddetails.basename) os.remove(result.filename) else gamedata.errormessage = "Failed to download " .. result.moddetails.title end - + if gamedata.errormessage == nil then - engine.button_handler({btn_hidden_close_download=result}) + core.button_handler({btn_hidden_close_download=result}) else - engine.button_handler({btn_hidden_close_download={successfull=false}}) + core.button_handler({btn_hidden_close_download={successfull=false}}) end end - ) - - return { - current_tab = "modstore_downloading", - is_dialog = true, - show_buttons = false, - ignore_menu_quit = true - } + ) then + print("ERROR: async event failed") + gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle + end + parent:hide() + modstore.showdownloading(modstore.lastmodtitle) + return true end end - break + return true end end + + return false +end + +-------------------------------------------------------------------------------- +-- @function [parent=#modstore] handle_events +function modstore.handle_events(this,event) + if (event == "MenuQuit") then + this:hide() + return true + end end -------------------------------------------------------------------------------- @@ -349,9 +328,9 @@ function modstore.update_modlist() modstore.modlist_unsorted.pagecount = 1 modstore.modlist_unsorted.page = 0 - engine.handle_async( + core.handle_async( function(param) - return engine.get_modstore_list() + return core.get_modstore_list() end, nil, function(result) @@ -368,7 +347,7 @@ function modstore.update_modlist() end modstore.modlist_unsorted.page = 0 modstore.fetchdetails() - engine.event_handler("Refresh") + core.event_handler("Refresh") end end ) @@ -379,9 +358,9 @@ end function modstore.fetchdetails() for i=1,#modstore.modlist_unsorted.data,1 do - engine.handle_async( + core.handle_async( function(param) - param.details = engine.get_modstore_details(tostring(param.modid)) + param.details = core.get_modstore_details(tostring(param.modid)) return param end, { @@ -396,7 +375,7 @@ function modstore.fetchdetails() modstore.modlist_unsorted.data[result.listindex].id ~= nil then modstore.modlist_unsorted.data[result.listindex].details = result.details - engine.event_handler("Refresh") + core.event_handler("Refresh") end end ) @@ -410,30 +389,30 @@ function modstore.getscreenshot(ypos,listentry) if listentry.details ~= nil and (listentry.details.screenshot_url == nil or listentry.details.screenshot_url == "") then - + if listentry.texturename == nil then listentry.texturename = modstore.basetexturedir .. "no_screenshot.png" end - + return "image[0,".. ypos .. ";3,2;" .. - engine.formspec_escape(listentry.texturename) .. "]" + core.formspec_escape(listentry.texturename) .. "]" end - + if listentry.details ~= nil and listentry.texturename == nil then --make sure we don't download multiple times listentry.texturename = "in progress" - + --prepare url and filename - local fullurl = engine.setting_get("modstore_download_url") .. + local fullurl = core.setting_get("modstore_download_url") .. listentry.details.screenshot_url local filename = os.tempfolder() .. "_MID_" .. listentry.id - + --trigger download - engine.handle_async( + core.handle_async( --first param is downloadfct function(param) - param.successfull = engine.download_file(param.fullurl,param.filename) + param.successfull = core.download_file(param.fullurl,param.filename) return param end, --second parameter is data passed to async job @@ -454,9 +433,9 @@ function modstore.getscreenshot(ypos,listentry) end end if found then - engine.event_handler("Refresh") + core.event_handler("Refresh") 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 @@ -466,9 +445,9 @@ function modstore.getscreenshot(ypos,listentry) if listentry.texturename ~= nil and listentry.texturename ~= "in progress" then return "image[0,".. ypos .. ";3,2;" .. - engine.formspec_escape(listentry.texturename) .. "]" + core.formspec_escape(listentry.texturename) .. "]" end - + return "" end @@ -476,7 +455,7 @@ end --@function [parent=#modstore] getshortmodinfo function modstore.getshortmodinfo(ypos,listentry,details) local retval = "" - + retval = retval .. "box[0," .. ypos .. ";11.4,1.75;#FFFFFF]" --screenshot @@ -484,19 +463,19 @@ function modstore.getshortmodinfo(ypos,listentry,details) --title + author retval = retval .."label[2.75," .. ypos .. ";" .. - engine.formspec_escape(details.title) .. " (" .. details.author .. ")]" + core.formspec_escape(details.title) .. " (" .. details.author .. ")]" --description local descriptiony = ypos + 0.5 retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" .. - engine.formspec_escape(details.description) .. ";]" - + core.formspec_escape(details.description) .. ";]" + --rating local ratingy = ypos retval = retval .."label[7," .. ratingy .. ";" .. fgettext("Rating") .. ":]" retval = retval .. "label[8.7," .. ratingy .. ";" .. details.rating .."]" - + --versions (IMPORTANT has to be defined AFTER rating) if details.versions ~= nil and #details.versions > 1 then @@ -507,7 +486,7 @@ function modstore.getshortmodinfo(ypos,listentry,details) if versions ~= "" then versions = versions .. "," end - + versions = versions .. details.versions[i].date:sub(1,10) end retval = retval .. versions .. ";1]" @@ -524,35 +503,38 @@ function modstore.getshortmodinfo(ypos,listentry,details) retval = retval .. fgettext("Install") .."]" end end - + return retval end -------------------------------------------------------------------------------- --@function [parent=#modstore] getmodlist function modstore.getmodlist(list,yoffset) - modstore.current_list = list - - if #list.data == 0 then - return "" - end - + if yoffset == nil then yoffset = 0 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 = "" - 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) .. "]" - scrollbar = scrollbar .. "box[11.6," .. (yoffset + 0.35) .. ";0.28," - .. (8.6 - yoffset) .. ";#000000]" - local scrollbarpos = (yoffset + 0.75) + - ((7.7 -yoffset)/(list.pagecount-1)) * list.page + scrollbar = scrollbar .. "box[11.6," .. sb_y_start .. ";0.28," .. sb_y_end .. ";#000000]" + local scrollbarpos = (sb_y_start + 0.5) + + ((sb_y_end -1.6)/(list.pagecount-1)) * list.page 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;^]" - 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]" local retval = "" @@ -578,22 +560,22 @@ function modstore.getmodlist(list,yoffset) if details ~= nil then local screenshot_ypos = yoffset +(i-1 - (list.page * modstore.modsperpage))*1.9 +0.2 - + retval = retval .. modstore.getshortmodinfo(screenshot_ypos, list.data[i], details) end end - - return retval .. scrollbar + + return retval .. scrollbar .. close_button end -------------------------------------------------------------------------------- --@function [parent=#modstore] getsearchpage -function modstore.getsearchpage() +function modstore.getsearchpage(tabview, name, tabdata) local retval = "" local search = "" - + if modstore.last_search ~= nil then search = modstore.last_search end @@ -602,9 +584,6 @@ function modstore.getsearchpage() "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 .. "]" - - --show 4 mods only - modstore.modsperpage = 4 retval = retval .. modstore.getmodlist( modstore.currentlist, @@ -613,3 +592,27 @@ function modstore.getsearchpage() return retval; 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 + diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua new file mode 100644 index 000000000..f752d1728 --- /dev/null +++ b/builtin/mainmenu/tab_credits.lua @@ -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 + } diff --git a/builtin/mainmenu/tab_mods.lua b/builtin/mainmenu/tab_mods.lua new file mode 100644 index 000000000..b258ce6c5 --- /dev/null +++ b/builtin/mainmenu/tab_mods.lua @@ -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 +} diff --git a/builtin/mainmenu/tab_multiplayer.lua b/builtin/mainmenu/tab_multiplayer.lua new file mode 100644 index 000000000..e8aad42c3 --- /dev/null +++ b/builtin/mainmenu/tab_multiplayer.lua @@ -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 + } diff --git a/builtin/mainmenu/tab_server.lua b/builtin/mainmenu/tab_server.lua new file mode 100644 index 000000000..1efe803b7 --- /dev/null +++ b/builtin/mainmenu/tab_server.lua @@ -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 + } diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua new file mode 100644 index 000000000..8710290cb --- /dev/null +++ b/builtin/mainmenu/tab_settings.lua @@ -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 + } diff --git a/builtin/mainmenu/tab_simple_main.lua b/builtin/mainmenu/tab_simple_main.lua new file mode 100644 index 000000000..46f4b6190 --- /dev/null +++ b/builtin/mainmenu/tab_simple_main.lua @@ -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 + } diff --git a/builtin/mainmenu/tab_singleplayer.lua b/builtin/mainmenu/tab_singleplayer.lua new file mode 100644 index 000000000..72f918806 --- /dev/null +++ b/builtin/mainmenu/tab_singleplayer.lua @@ -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 + } diff --git a/builtin/mainmenu/tab_texturepacks.lua b/builtin/mainmenu/tab_texturepacks.lua new file mode 100644 index 000000000..784480415 --- /dev/null +++ b/builtin/mainmenu/tab_texturepacks.lua @@ -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 + } diff --git a/builtin/mainmenu/textures.lua b/builtin/mainmenu/textures.lua index 998fc2199..cec12235c 100644 --- a/builtin/mainmenu/textures.lua +++ b/builtin/mainmenu/textures.lua @@ -20,11 +20,11 @@ mm_texture = {} -------------------------------------------------------------------------------- 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 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 end @@ -55,14 +55,14 @@ function mm_texture.reset() mm_texture.clear("header") mm_texture.clear("footer") - engine.set_clouds(false) + core.set_clouds(false) mm_texture.set_generic("footer") mm_texture.set_generic("header") if not have_bg and - engine.setting_getbool("enable_clouds") then - engine.set_clouds(true) + core.setting_getbool("menu_clouds") then + core.set_clouds(true) end end @@ -72,7 +72,7 @@ function mm_texture.update_game(gamedetails) return end - local have_bg = false + local have_bg = false local have_overlay = mm_texture.set_game("overlay",gamedetails) if not have_overlay then @@ -81,11 +81,11 @@ function mm_texture.update_game(gamedetails) mm_texture.clear("header") mm_texture.clear("footer") - engine.set_clouds(false) + core.set_clouds(false) if not have_bg and - engine.setting_getbool("enable_clouds") then - engine.set_clouds(true) + core.setting_getbool("menu_clouds") then + core.set_clouds(true) end mm_texture.set_game("footer",gamedetails) @@ -96,24 +96,24 @@ end -------------------------------------------------------------------------------- function mm_texture.clear(identifier) - engine.set_background(identifier,"") + core.set_background(identifier,"") end -------------------------------------------------------------------------------- function mm_texture.set_generic(identifier) --try texture pack first if mm_texture.texturepack ~= nil then - local path = mm_texture.texturepack .. DIR_DELIM .."menu_" .. + local path = mm_texture.texturepack .. DIR_DELIM .."menu_" .. identifier .. ".png" - if engine.set_background(identifier,path) then + if core.set_background(identifier,path) then return true end end if mm_texture.defaulttexturedir ~= nil then - local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" .. + local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" .. identifier .. ".png" - if engine.set_background(identifier,path) then + if core.set_background(identifier,path) then return true end end @@ -131,14 +131,14 @@ function mm_texture.set_game(identifier,gamedetails) if mm_texture.texturepack ~= nil then local path = mm_texture.texturepack .. DIR_DELIM .. gamedetails.id .. "_menu_" .. identifier .. ".png" - if engine.set_background(identifier,path) then + if core.set_background(identifier,path) then return true end end - local path = gamedetails.path .. DIR_DELIM .."menu" .. + local path = gamedetails.path .. DIR_DELIM .."menu" .. DIR_DELIM .. identifier .. ".png" - if engine.set_background(identifier,path) then + if core.set_background(identifier,path) then return true end diff --git a/doc/fst_api.txt b/doc/fst_api.txt new file mode 100644 index 000000000..54f2d07a6 --- /dev/null +++ b/doc/fst_api.txt @@ -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 +} diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 109aededa..cd44fa815 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Mainmenu API Reference 0.4.9 +Minetest Lua Mainmenu API Reference 0.4.10 ======================================== Introduction @@ -8,14 +8,14 @@ Description of formspec language to show your menu is in lua_api.txt Callbacks --------- -engine.buttonhandler(fields): called when a button is pressed. +core.buttonhandler(fields): called when a button is pressed. ^ fields = {name1 = value1, name2 = value2, ...} -engine.event_handler(event) +core.event_handler(event) ^ event: "MenuQuit", "KeyEnter", "ExitButton" or "EditBoxEnter" 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>, password = <password>, @@ -27,15 +27,15 @@ The "gamedata" table is read when calling engine.start(). It should contain: Functions --------- -engine.start() -engine.close() +core.start() +core.close() Filesystem: -engine.get_scriptdir() +core.get_scriptdir() ^ returns directory of script -engine.get_modpath() (possible in async calls) +core.get_modpath() (possible in async calls) ^ 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 ^ returns { 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>, rating = <float value of current rating> } -engine.get_modstore_list() (possible in async calls) +core.get_modstore_list() (possible in async calls) ^ returns { [1] = { id = <numeric id of mod in modstore>, @@ -55,60 +55,60 @@ engine.get_modstore_list() (possible in async calls) basename = <basename for mod> } } -engine.get_gamepath() (possible in async calls) +core.get_gamepath() (possible in async calls) ^ returns path to global gamepath -engine.get_texturepath() (possible in async calls) +core.get_texturepath() (possible in async calls) ^ 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 ^ onlydirs should result contain only dirs? ^ 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) ^ 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) ^ 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 ^ destination folder ^ keep_source DEFAULT true --> if set to false source is deleted after copying ^ returns true/false -engine.extract_zip(zipfile,destination) [unzip within path required] +core.extract_zip(zipfile,destination) [unzip within path required] ^ zipfile to extract ^ destination folder to extract to ^ returns true/false -engine.download_file(url,target) (possible in async calls) +core.download_file(url,target) (possible in async calls) ^ url to download ^ target to store to ^ returns true/false -engine.get_version() (possible in async calls) +core.get_version() (possible in async calls) ^ returns current core version -engine.sound_play(spec, looped) -> handle +core.sound_play(spec, looped) -> handle ^ spec = SimpleSoundSpec (see lua-api.txt) ^ looped = bool -engine.sound_stop(handle) +core.sound_stop(handle) Formspec: -engine.update_formspec(formspec) -engine.get_table_index(tablename) -> index +core.update_formspec(formspec) +core.get_table_index(tablename) -> index ^ can also handle textlists -engine.formspec_escape(string) -> string +core.formspec_escape(string) -> string ^ 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} ^ 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} ^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click) GUI: -engine.set_background(type, texturepath) +core.set_background(type, texturepath) ^ type: "background", "overlay", "header" or "footer" -engine.set_clouds(<true/false>) -engine.set_topleft_text(text) -engine.show_keys_menu() -engine.file_open_dialog(formname,caption) +core.set_clouds(<true/false>) +core.set_topleft_text(text) +core.show_keys_menu() +core.file_open_dialog(formname,caption) ^ shows a file open dialog ^ formname is base name of dialog response returned in fields ^ -if dialog was accepted "_accepted" @@ -116,7 +116,7 @@ engine.file_open_dialog(formname,caption) ^ -if dialog was canceled "_cancelled" ^ will be added to fieldname value is set to formname itself ^ returns nil or selected file/folder -engine.get_screen_info() +core.get_screen_info() ^ returns { density = <screen density 0.75,1.0,2.0,3.0 ... (dpi)>, display_width = <width of display>, @@ -126,7 +126,7 @@ engine.get_screen_info() } Games: -engine.get_game(index) +core.get_game(index) ^ returns { id = <id>, path = <full path to game>, @@ -136,10 +136,10 @@ engine.get_game(index) DEPRECATED: 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: -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" ^ returns { [1] = { @@ -156,24 +156,24 @@ engine.get_favorites(location) -> list of favorites (possible in async calls) port = <port> }, } -engine.delete_favorite(id, location) -> success +core.delete_favorite(id, location) -> success 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) -engine.log(line) (possible in async calls) -engine.log(loglevel, line) (possible in async calls) +core.log(line) (possible in async calls) +core.log(loglevel, line) (possible in async calls) ^ loglevel one of "error", "action", "info", "verbose" Settings: -engine.setting_set(name, value) -engine.setting_get(name) -> string or nil (possible in async calls) -engine.setting_setbool(name, value) -engine.setting_getbool(name) -> bool or nil (possible in async calls) -engine.setting_save() -> nil, save all settings to config file +core.setting_set(name, value) +core.setting_get(name) -> string or nil (possible in async calls) +core.setting_setbool(name, value) +core.setting_getbool(name) -> bool or nil (possible in async calls) +core.setting_save() -> nil, save all settings to config file Worlds: -engine.get_worlds() -> list of worlds (possible in async calls) +core.get_worlds() -> list of worlds (possible in async calls) ^ returns { [1] = { path = <full path to world>, @@ -181,16 +181,16 @@ engine.get_worlds() -> list of worlds (possible in async calls) gameid = <gameid of world>, }, } -engine.create_world(worldname, gameid) -engine.delete_world(index) +core.create_world(worldname, gameid) +core.delete_world(index) Helpers: -engine.gettext(string) -> string +core.gettext(string) -> string ^ look up the translation of a string in the gettext message catalog fgettext(string, ...) -> string -^ call engine.gettext(string), replace "$1"..."$9" with the given -^ extra arguments, call engine.formspec_escape and return the result -engine.parse_json(string[, nullvalue]) -> something (possible in async calls) +^ call core.gettext(string), replace "$1"..."$9" with the given +^ extra arguments, call core.formspec_escape and return the result +core.parse_json(string[, nullvalue]) -> something (possible in async calls) ^ see core.parse_json (lua_api.txt) dump(obj, dumped={}) ^ 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 Async: -engine.handle_async(async_job,parameters,finished) +core.handle_async(async_job,parameters,finished) ^ execute a function asynchronously ^ async_job is a function receiving one parameter and returning one parameter ^ parameters parameter table passed to async_job @@ -212,8 +212,8 @@ engine.handle_async(async_job,parameters,finished) Limitations of Async operations -No access to global lua variables, don't even try -Limited set of available functions - e.g. No access to functions modifying menu like engine.start,engine.close, - engine.file_open_dialog + e.g. No access to functions modifying menu like core.start,core.close, + core.file_open_dialog Class reference |