From: sapier Date: Fri, 18 Apr 2014 13:39:15 +0000 (+0200) Subject: Add formspec toolkit and refactor mainmenu to use it X-Git-Tag: 0.4.10~124 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=c3984569c06dc3c2890516e95adc38dcab9ec89a;p=oweals%2Fminetest.git 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 --- diff --git a/builtin/common/filterlist.lua b/builtin/common/filterlist.lua new file mode 100644 index 000000000..99c4bca1c --- /dev/null +++ b/builtin/common/filterlist.lua @@ -0,0 +1,317 @@ +--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. + +-------------------------------------------------------------------------------- +-- 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 -- +-- pass following functions: -- +-- raw_fct() (mandatory): -- +-- function returning a table containing the elements to be filtered -- +-- compare_fct(element1,element2) (mandatory): -- +-- function returning true/false if element1 is same element as element2 -- +-- uid_match_fct(element1,uid) (optional) -- +-- function telling if uid is attached to element1 -- +-- filter_fct(element,filtercriteria) (optional) -- +-- function returning true/false if filtercriteria met to element -- +-- fetch_param (optional) -- +-- parameter passed to raw_fct to aquire correct raw data -- +-- -- +-------------------------------------------------------------------------------- +filterlist = {} + +-------------------------------------------------------------------------------- +function filterlist.refresh(this) + this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param) + filterlist.process(this) +end + +-------------------------------------------------------------------------------- +function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param) + + assert((raw_fct ~= nil) and (type(raw_fct) == "function")) + assert((compare_fct ~= nil) and (type(compare_fct) == "function")) + + local this = {} + + this.m_raw_list_fct = raw_fct + this.m_compare_fct = compare_fct + this.m_filter_fct = filter_fct + this.m_uid_match_fct = uid_match_fct + + this.m_filtercriteria = nil + this.m_fetch_param = fetch_param + + this.m_sortmode = "none" + this.m_sort_list = {} + + 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 +end + +-------------------------------------------------------------------------------- +function filterlist.add_sort_mechanism(this,name,fct) + this.m_sort_list[name] = fct +end + +-------------------------------------------------------------------------------- +function filterlist.set_filtercriteria(this,criteria) + if criteria == this.m_filtercriteria and + type(criteria) ~= "table" then + return + end + this.m_filtercriteria = criteria + filterlist.process(this) +end + +-------------------------------------------------------------------------------- +function filterlist.get_filtercriteria(this) + return this.m_filtercriteria +end + +-------------------------------------------------------------------------------- +--supported sort mode "alphabetic|none" +function filterlist.set_sortmode(this,mode) + if (mode == this.m_sortmode) then + return + end + this.m_sortmode = mode + filterlist.process(this) +end + +-------------------------------------------------------------------------------- +function filterlist.get_list(this) + return this.m_processed_list +end + +-------------------------------------------------------------------------------- +function filterlist.get_raw_list(this) + return this.m_raw_list +end + +-------------------------------------------------------------------------------- +function filterlist.get_raw_element(this,idx) + if type(idx) ~= "number" then + idx = tonumber(idx) + end + + if idx ~= nil and idx > 0 and idx < #this.m_raw_list then + return this.m_raw_list[idx] + end + + return nil +end + +-------------------------------------------------------------------------------- +function filterlist.get_raw_index(this,listindex) + assert(this.m_processed_list ~= nil) + + if listindex ~= nil and listindex > 0 and + listindex <= #this.m_processed_list then + local entry = this.m_processed_list[listindex] + + for i,v in ipairs(this.m_raw_list) do + + if this.m_compare_fct(v,entry) then + return i + end + end + end + + return 0 +end + +-------------------------------------------------------------------------------- +function filterlist.get_current_index(this,listindex) + assert(this.m_processed_list ~= nil) + + if listindex ~= nil and listindex > 0 and + listindex <= #this.m_raw_list then + local entry = this.m_raw_list[listindex] + + for i,v in ipairs(this.m_processed_list) do + + if this.m_compare_fct(v,entry) then + return i + end + end + end + + return 0 +end + +-------------------------------------------------------------------------------- +function filterlist.process(this) + assert(this.m_raw_list ~= nil) + + if this.m_sortmode == "none" and + this.m_filtercriteria == nil then + this.m_processed_list = this.m_raw_list + return + end + + this.m_processed_list = {} + + for k,v in pairs(this.m_raw_list) do + if this.m_filtercriteria == nil or + this.m_filter_fct(v,this.m_filtercriteria) then + table.insert(this.m_processed_list,v) + end + end + + if this.m_sortmode == "none" then + return + end + + if this.m_sort_list[this.m_sortmode] ~= nil and + type(this.m_sort_list[this.m_sortmode]) == "function" then + + this.m_sort_list[this.m_sortmode](this) + end +end + +-------------------------------------------------------------------------------- +function filterlist.size(this) + if this.m_processed_list == nil then + return 0 + end + + return #this.m_processed_list +end + +-------------------------------------------------------------------------------- +function filterlist.uid_exists_raw(this,uid) + for i,v in ipairs(this.m_raw_list) do + if this.m_uid_match_fct(v,uid) then + return true + end + end + return false +end + +-------------------------------------------------------------------------------- +function filterlist.raw_index_by_uid(this, uid) + local elementcount = 0 + local elementidx = 0 + for i,v in ipairs(this.m_raw_list) do + if this.m_uid_match_fct(v,uid) then + elementcount = elementcount +1 + elementidx = i + end + end + + + -- If there are more elements than one with same name uid can't decide which + -- one is meant. This shouldn't be possible but just for sure. + if elementcount > 1 then + elementidx=0 + end + + return elementidx +end + +-------------------------------------------------------------------------------- +-- COMMON helper functions -- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +function compare_worlds(world1,world2) + + if world1.path ~= world2.path then + return false + end + + if world1.name ~= world2.name then + return false + end + + if world1.gameid ~= world2.gameid then + return false + end + + return true +end + +-------------------------------------------------------------------------------- +function sort_worlds_alphabetic(this) + + table.sort(this.m_processed_list, function(a, b) + --fixes issue #857 (crash due to sorting nil in worldlist) + if a == nil or b == nil then + if a == nil and b ~= nil then return false end + if b == nil and a ~= nil then return true end + return false + end + if a.name:lower() == b.name:lower() then + return a.name < b.name + end + return a.name:lower() < b.name:lower() + end) +end + +-------------------------------------------------------------------------------- +function sort_mod_list(this) + + table.sort(this.m_processed_list, function(a, b) + -- Show game mods at bottom + if a.typ ~= b.typ then + return b.typ == "game_mod" + end + -- If in same or no modpack, sort by name + if a.modpack == b.modpack then + if a.name:lower() == b.name:lower() then + return a.name < b.name + end + return a.name:lower() < b.name:lower() + -- Else compare name to modpack name + else + -- Always show modpack pseudo-mod on top of modpack mod list + if a.name == b.modpack then + return true + elseif b.name == a.modpack then + return false + end + + local name_a = a.modpack or a.name + local name_b = b.modpack or b.name + if name_a:lower() == name_b:lower() then + return name_a < name_b + end + return name_a:lower() < name_b:lower() + end + end) +end 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/filterlist.lua b/builtin/mainmenu/filterlist.lua deleted file mode 100644 index 379a5cea9..000000000 --- a/builtin/mainmenu/filterlist.lua +++ /dev/null @@ -1,301 +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. - --------------------------------------------------------------------------------- --- Generic implementation of a filter/sortable list -- --- Usage: -- --- Filterlist needs to be initialized on creation. To achieve this you need to -- --- pass following functions: -- --- raw_fct() (mandatory): -- --- function returning a table containing the elements to be filtered -- --- compare_fct(element1,element2) (mandatory): -- --- function returning true/false if element1 is same element as element2 -- --- uid_match_fct(element1,uid) (optional) -- --- function telling if uid is attached to element1 -- --- filter_fct(element,filtercriteria) (optional) -- --- function returning true/false if filtercriteria met to element -- --- fetch_param (optional) -- --- parameter passed to raw_fct to aquire correct raw data -- --- -- --------------------------------------------------------------------------------- -filterlist = {} - --------------------------------------------------------------------------------- -function filterlist.refresh(this) - this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param) - filterlist.process(this) -end - --------------------------------------------------------------------------------- -function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param) - - assert((raw_fct ~= nil) and (type(raw_fct) == "function")) - assert((compare_fct ~= nil) and (type(compare_fct) == "function")) - - local this = {} - - this.m_raw_list_fct = raw_fct - this.m_compare_fct = compare_fct - this.m_filter_fct = filter_fct - this.m_uid_match_fct = uid_match_fct - - this.m_filtercriteria = nil - this.m_fetch_param = fetch_param - - this.m_sortmode = "none" - this.m_sort_list = {} - - this.m_processed_list = nil - this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param) - - filterlist.process(this) - - return this -end - --------------------------------------------------------------------------------- -function filterlist.add_sort_mechanism(this,name,fct) - this.m_sort_list[name] = fct -end - --------------------------------------------------------------------------------- -function filterlist.set_filtercriteria(this,criteria) - if criteria == this.m_filtercriteria and - type(criteria) ~= "table" then - return - end - this.m_filtercriteria = criteria - filterlist.process(this) -end - --------------------------------------------------------------------------------- -function filterlist.get_filtercriteria(this) - return this.m_filtercriteria -end - --------------------------------------------------------------------------------- ---supported sort mode "alphabetic|none" -function filterlist.set_sortmode(this,mode) - if (mode == this.m_sortmode) then - return - end - this.m_sortmode = mode - filterlist.process(this) -end - --------------------------------------------------------------------------------- -function filterlist.get_list(this) - return this.m_processed_list -end - --------------------------------------------------------------------------------- -function filterlist.get_raw_list(this) - return this.m_raw_list -end - --------------------------------------------------------------------------------- -function filterlist.get_raw_element(this,idx) - if type(idx) ~= "number" then - idx = tonumber(idx) - end - - if idx ~= nil and idx > 0 and idx < #this.m_raw_list then - return this.m_raw_list[idx] - end - - return nil -end - --------------------------------------------------------------------------------- -function filterlist.get_raw_index(this,listindex) - assert(this.m_processed_list ~= nil) - - if listindex ~= nil and listindex > 0 and - listindex <= #this.m_processed_list then - local entry = this.m_processed_list[listindex] - - for i,v in ipairs(this.m_raw_list) do - - if this.m_compare_fct(v,entry) then - return i - end - end - end - - return 0 -end - --------------------------------------------------------------------------------- -function filterlist.get_current_index(this,listindex) - assert(this.m_processed_list ~= nil) - - if listindex ~= nil and listindex > 0 and - listindex <= #this.m_raw_list then - local entry = this.m_raw_list[listindex] - - for i,v in ipairs(this.m_processed_list) do - - if this.m_compare_fct(v,entry) then - return i - end - end - end - - return 0 -end - --------------------------------------------------------------------------------- -function filterlist.process(this) - assert(this.m_raw_list ~= nil) - - if this.m_sortmode == "none" and - this.m_filtercriteria == nil then - this.m_processed_list = this.m_raw_list - return - end - - this.m_processed_list = {} - - for k,v in pairs(this.m_raw_list) do - if this.m_filtercriteria == nil or - this.m_filter_fct(v,this.m_filtercriteria) then - table.insert(this.m_processed_list,v) - end - end - - if this.m_sortmode == "none" then - return - end - - if this.m_sort_list[this.m_sortmode] ~= nil and - type(this.m_sort_list[this.m_sortmode]) == "function" then - - this.m_sort_list[this.m_sortmode](this) - end -end - --------------------------------------------------------------------------------- -function filterlist.size(this) - if this.m_processed_list == nil then - return 0 - end - - return #this.m_processed_list -end - --------------------------------------------------------------------------------- -function filterlist.uid_exists_raw(this,uid) - for i,v in ipairs(this.m_raw_list) do - if this.m_uid_match_fct(v,uid) then - return true - end - end - return false -end - --------------------------------------------------------------------------------- -function filterlist.raw_index_by_uid(this, uid) - local elementcount = 0 - local elementidx = 0 - for i,v in ipairs(this.m_raw_list) do - if this.m_uid_match_fct(v,uid) then - elementcount = elementcount +1 - elementidx = i - end - end - - - -- If there are more elements than one with same name uid can't decide which - -- one is meant. This shouldn't be possible but just for sure. - if elementcount > 1 then - elementidx=0 - end - - return elementidx -end - --------------------------------------------------------------------------------- --- COMMON helper functions -- --------------------------------------------------------------------------------- - --------------------------------------------------------------------------------- -function compare_worlds(world1,world2) - - if world1.path ~= world2.path then - return false - end - - if world1.name ~= world2.name then - return false - end - - if world1.gameid ~= world2.gameid then - return false - end - - return true -end - --------------------------------------------------------------------------------- -function sort_worlds_alphabetic(this) - - table.sort(this.m_processed_list, function(a, b) - --fixes issue #857 (crash due to sorting nil in worldlist) - if a == nil or b == nil then - if a == nil and b ~= nil then return false end - if b == nil and a ~= nil then return true end - return false - end - if a.name:lower() == b.name:lower() then - return a.name < b.name - end - return a.name:lower() < b.name:lower() - end) -end - --------------------------------------------------------------------------------- -function sort_mod_list(this) - - table.sort(this.m_processed_list, function(a, b) - -- Show game mods at bottom - if a.typ ~= b.typ then - return b.typ == "game_mod" - end - -- If in same or no modpack, sort by name - if a.modpack == b.modpack then - if a.name:lower() == b.name:lower() then - return a.name < b.name - end - return a.name:lower() < b.name:lower() - -- Else compare name to modpack name - else - -- Always show modpack pseudo-mod on top of modpack mod list - if a.name == b.modpack then - return true - elseif b.name == a.modpack then - return false - end - - local name_a = a.modpack or a.name - local name_b = b.modpack or b.name - if name_a:lower() == name_b:lower() then - return name_a < name_b - end - return name_a:lower() < name_b:lower() - end - end) -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 @@ -17,146 +17,9 @@ 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) ,".. - "Ryan Kwolek (kwolekr) ,".. - "PilzAdam ," .. - "Ilya Zhuravlev (xyz) ,".. - "Lisa Milne (darkrose) ,".. - "Maciej Kasatkin (RealBadAngel) ,".. - "proller ,".. - "sfan5 ,".. - "kahrl ,".. - "sapier,".. - "ShadowNinja ,".. - "Nathanael Courant (Nore/Novatux) ,".. - "BlockMen,".. - ",".. - "#FFFF00" .. fgettext("Active Contributors") .. "," .. - "Vanessa Ezekowitz (VanessaE) ,".. - "Jurgen Doser (doserj) ,".. - "Jeija ,".. - "MirceaKitsune ,".. - "dannydark ,".. - "0gb.us <0gb.us@0gb.us>,".. - "," .. - "#FFFF00" .. fgettext("Previous Contributors") .. "," .. - "Guiseppe Bilotta (Oblomov) ,".. - "Jonathan Neuschafer ,".. - "Nils Dagsson Moskopp (erlehmann) ,".. - "Constantin Wenger (SpeedProg) ,".. - "matttpt ,".. - "JacobF ,".. - ";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 @@ -406,104 +280,6 @@ function modmgr.render_modlist(render_list) return retval 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 = "" @@ -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,234 +378,19 @@ 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 @@ -938,58 +452,6 @@ function modmgr.preparemodlist(data) return retval 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 @@ -1015,29 +477,6 @@ function modmgr.comparemod(elem1,elem2) return true 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) @@ -1045,7 +484,7 @@ function modmgr.mod_exists(basename) 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/modstore.lua deleted file mode 100644 index ef7fd0165..000000000 --- a/builtin/mainmenu/modstore.lua +++ /dev/null @@ -1,615 +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. - --------------------------------------------------------------------------------- - ---modstore implementation -modstore = {} - --------------------------------------------------------------------------------- --- @function [parent=#modstore] init -function modstore.init() - modstore.tabnames = {} - - table.insert(modstore.tabnames,"dialog_modstore_unsorted") - table.insert(modstore.tabnames,"dialog_modstore_search") - - modstore.modsperpage = 5 - - modstore.basetexturedir = engine.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 - modstore.modlist_unsorted.data ~= nil then - return modstore.modlist_unsorted.data - end - return {} - end, - function(element,modid) - if element.id == modid then - return true - end - return false - end, --compare fct - nil, --uid match fct - function(element,substring) - if substring == nil or - substring == "" then - 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 - return true - end - return false - end --filter fct - ) - - modstore.current_list = nil -end - --------------------------------------------------------------------------------- --- @function [parent=#modstore] nametoindex -function modstore.nametoindex(name) - - for i=1,#modstore.tabnames,1 do - if modstore.tabnames[i] == name then - return i - end - end - - return 1 -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] gettab -function modstore.gettab(tabname) - local retval = "" - - local is_modstore_tab = false - - if tabname == "dialog_modstore_unsorted" then - modstore.modsperpage = 5 - retval = modstore.getmodlist(modstore.modlist_unsorted) - is_modstore_tab = true - end - - if tabname == "dialog_modstore_search" then - retval = modstore.getsearchpage() - is_modstore_tab = true - end - - if is_modstore_tab then - return modstore.tabheader(tabname) .. retval - end - - if tabname == "modstore_mod_installed" then - return modstore.getsuccessfuldialog() - end - - if tabname == "modstore_downloading" then - return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") .. - " " .. modstore.lastmodtitle .. " " .. - fgettext("please wait...") .. "]" - end - - return "" -end - --------------------------------------------------------------------------------- --- @function [parent=#modstore] tabheader -function modstore.tabheader(tabname) - local retval = "size[12,10.25,true]" - retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" .. - "Unsorted,Search;" .. - modstore.nametoindex(tabname) .. ";true;false]" .. - "button[4,9.9;4,0.5;btn_modstore_close;" .. - fgettext("Close modstore") .. "]" - - return retval -end - --------------------------------------------------------------------------------- --- @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 - - 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 - end - - if fields["btn_modstore_page_down"] then - if modstore.current_list ~= nil and - modstore.current_list.page 1 then - local versiony = ypos + 0.05 - retval = retval .. "dropdown[9.1," .. versiony .. ";2.48,0.25;dd_version" .. details.id .. ";" - local versions = "" - for i=1,#details.versions , 1 do - if versions ~= "" then - versions = versions .. "," - end - - versions = versions .. details.versions[i].date:sub(1,10) - end - retval = retval .. versions .. ";1]" - end - - if details.basename then - --install button - local buttony = ypos + 1.2 - retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. details.id .. ";" - - if modmgr.mod_exists(details.basename) then - retval = retval .. fgettext("re-Install") .."]" - else - 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 scrollbar = "" - scrollbar = scrollbar .. "label[0.1,9.5;" - .. 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," ..scrollbarpos .. ";0.28,0.5;#32CD32]" - scrollbar = scrollbar .. "button[11.6," .. (yoffset + (0.3)) - .. ";0.5,0.5;btn_modstore_page_up;^]" - scrollbar = scrollbar .. "button[11.6," .. 9.0 - .. ";0.5,0.5;btn_modstore_page_down;v]" - - local retval = "" - - local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage - - if (endmod > #list.data) then - endmod = #list.data - end - - for i=(list.page * modstore.modsperpage) +1, endmod, 1 do - --getmoddetails - local details = list.data[i].details - - if details == nil then - details = {} - details.title = list.data[i].title - details.author = "" - details.rating = -1 - details.description = "" - end - - 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 -end - --------------------------------------------------------------------------------- ---@function [parent=#modstore] getsearchpage -function modstore.getsearchpage() - local retval = "" - local search = "" - - if modstore.last_search ~= nil then - search = modstore.last_search - end - - retval = retval .. - "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, - 1.75) - - return retval; -end - diff --git a/builtin/mainmenu/store.lua b/builtin/mainmenu/store.lua new file mode 100644 index 000000000..48433e58d --- /dev/null +++ b/builtin/mainmenu/store.lua @@ -0,0 +1,618 @@ +--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. + +-------------------------------------------------------------------------------- + +--modstore implementation +modstore = {} + +-------------------------------------------------------------------------------- +-- @function [parent=#modstore] init +function modstore.init(size, unsortedmods, searchmods) + + modstore.mods_on_unsorted_page = unsortedmods + modstore.mods_on_search_page = searchmods + modstore.modsperpage = modstore.mods_on_unsorted_page + + 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 + modstore.modlist_unsorted.data ~= nil then + return modstore.modlist_unsorted.data + end + return {} + end, + function(element,modid) + if element.id == modid then + return true + end + return false + end, --compare fct + nil, --uid match fct + function(element,substring) + if substring == nil or + substring == "" then + 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 + return true + end + return false + end --filter fct + ) + + 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 + +-------------------------------------------------------------------------------- +-- @function [parent=#modstore] nametoindex +function modstore.nametoindex(name) + + for i=1,#modstore.tabnames,1 do + if modstore.tabnames[i] == name then + return i + end + end + + return 1 +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 + + this:delete() + return true + end + + return false + end, + nil, + modstore.tv_store) + + new_dlg.data.title = title + new_dlg:show() +end + +-------------------------------------------------------------------------------- +-- @function [parent=#modstore] successfulldialog +function modstore.successfulldialog() + local new_dlg = dialog_create("store_downloading", + function(data) + local retval = "" + 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;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]" + + 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 true + end + + return false + end, + nil, + modstore.tv_store) + + new_dlg.data.title = title + new_dlg:show() +end + +-------------------------------------------------------------------------------- +-- @function [parent=#modstore] handle_buttons +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 + if modstore.current_list ~= nil and + modstore.current_list.page 1 then + local versiony = ypos + 0.05 + retval = retval .. "dropdown[9.1," .. versiony .. ";2.48,0.25;dd_version" .. details.id .. ";" + local versions = "" + for i=1,#details.versions , 1 do + if versions ~= "" then + versions = versions .. "," + end + + versions = versions .. details.versions[i].date:sub(1,10) + end + retval = retval .. versions .. ";1]" + end + + if details.basename then + --install button + local buttony = ypos + 1.2 + retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. details.id .. ";" + + if modmgr.mod_exists(details.basename) then + retval = retval .. fgettext("re-Install") .."]" + else + retval = retval .. fgettext("Install") .."]" + end + end + + return retval +end + +-------------------------------------------------------------------------------- +--@function [parent=#modstore] getmodlist +function modstore.getmodlist(list,yoffset) + modstore.current_list = list + + 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,".. (sb_y_end + 0.25 + yoffset) ..";" + .. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]" + 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," .. (sb_y_start) + .. ";0.5,0.5;btn_modstore_page_up;^]" + scrollbar = scrollbar .. "button[11.6," .. (sb_y_start + sb_y_end - 0.5) + .. ";0.5,0.5;btn_modstore_page_down;v]" + + local retval = "" + + local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage + + if (endmod > #list.data) then + endmod = #list.data + end + + for i=(list.page * modstore.modsperpage) +1, endmod, 1 do + --getmoddetails + local details = list.data[i].details + + if details == nil then + details = {} + details.title = list.data[i].title + details.author = "" + details.rating = -1 + details.description = "" + end + + 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 .. close_button +end + +-------------------------------------------------------------------------------- +--@function [parent=#modstore] getsearchpage +function modstore.getsearchpage(tabview, name, tabdata) + local retval = "" + local search = "" + + if modstore.last_search ~= nil then + search = modstore.last_search + end + + retval = retval .. + "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 .. "]" + + retval = retval .. + modstore.getmodlist( + modstore.currentlist, + 1.75) + + 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) ,".. + "Ryan Kwolek (kwolekr) ,".. + "PilzAdam ," .. + "Ilya Zhuravlev (xyz) ,".. + "Lisa Milne (darkrose) ,".. + "Maciej Kasatkin (RealBadAngel) ,".. + "proller ,".. + "sfan5 ,".. + "kahrl ,".. + "sapier,".. + "ShadowNinja ,".. + "Nathanael Courant (Nore/Novatux) ,".. + "BlockMen,".. + ",".. + "#FFFF00" .. fgettext("Active Contributors") .. "," .. + "Vanessa Ezekowitz (VanessaE) ,".. + "Jurgen Doser (doserj) ,".. + "Jeija ,".. + "MirceaKitsune ,".. + "dannydark ,".. + "0gb.us <0gb.us@0gb.us>,".. + "," .. + "#FFFF00" .. fgettext("Previous Contributors") .. "," .. + "Guiseppe Bilotta (Oblomov) ,".. + "Jonathan Neuschafer ,".. + "Nils Dagsson Moskopp (erlehmann) ,".. + "Constantin Wenger (SpeedProg) ,".. + "matttpt ,".. + "JacobF ,".. + ";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 = , 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 = , @@ -47,7 +47,7 @@ engine.get_modstore_details(modid) (possible in async calls) license = , rating = } -engine.get_modstore_list() (possible in async calls) +core.get_modstore_list() (possible in async calls) ^ returns { [1] = { id = , @@ -55,60 +55,60 @@ engine.get_modstore_list() (possible in async calls) basename = } } -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() -engine.set_topleft_text(text) -engine.show_keys_menu() -engine.file_open_dialog(formname,caption) +core.set_clouds() +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 = , display_width = , @@ -126,7 +126,7 @@ engine.get_screen_info() } Games: -engine.get_game(index) +core.get_game(index) ^ returns { id = , path = , @@ -136,10 +136,10 @@ engine.get_game(index) DEPRECATED: addon_mods_paths = {[1] = ,}, } -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 = }, } -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 = , @@ -181,16 +181,16 @@ engine.get_worlds() -> list of worlds (possible in async calls) gameid = , }, } -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