From 6d3dc6ce06ab25156a4a2d84ae818b8a76edabd3 Mon Sep 17 00:00:00 2001 From: Maksim Gamarnik Date: Tue, 12 May 2015 10:59:17 +0300 Subject: [PATCH] New MainMenu, update WversionManager, Makefile change New MainMenu by 4aiman WVersionManager - 1.3 Makefile - rename output apk --- build/android/Makefile | 10 +- build/android/libs/wversionmanager-1.2.jar | Bin 9956 -> 0 bytes build/android/libs/wversionmanager-1.3.jar | Bin 0 -> 10769 bytes builtin/ProFi.lua | 463 +++++++ builtin/common/filterlist.lua | 2 +- builtin/common/misc_helpers.lua | 111 +- builtin/common/serialize.lua | 11 +- builtin/common/strict.lua | 5 - builtin/fstk/buttonbar.lua | 2 +- builtin/fstk/dialog.lua | 2 +- builtin/fstk/tabview.lua | 88 +- builtin/fstk/ui.lua | 4 +- builtin/game/auth.lua | 31 +- builtin/game/chatcommands.lua | 69 +- builtin/game/deprecated.lua | 2 +- builtin/game/detached_inventory.lua | 2 +- builtin/game/falling.lua | 58 +- builtin/game/features.lua | 2 +- builtin/game/init.lua | 6 +- builtin/game/item.lua | 62 +- builtin/game/item_entity.lua | 17 +- builtin/game/misc.lua | 16 +- builtin/game/mod_debugging.lua | 126 ++ builtin/game/mod_profiling.lua | 2 +- builtin/game/privileges.lua | 2 +- builtin/game/register.lua | 586 +++++---- builtin/game/stat.lua | 75 ++ builtin/game/static_spawn.lua | 2 +- builtin/init.lua | 13 +- builtin/key_value_storage.lua | 26 + builtin/mainmenu/common.lua | 354 ++--- builtin/mainmenu/dlg_add_server.lua | 111 ++ builtin/mainmenu/dlg_config_world.lua | 466 +++---- builtin/mainmenu/dlg_create_world.lua | 199 +-- builtin/mainmenu/dlg_delete_mod.lua | 71 +- builtin/mainmenu/dlg_delete_world.lua | 65 +- builtin/mainmenu/dlg_rename_modpack.lua | 68 +- builtin/mainmenu/fm_gamemgr.lua | 321 +++++ builtin/mainmenu/{init.lua => fm_init.lua} | 145 +-- builtin/mainmenu/fm_init_orig.lua | 1361 ++++++++++++++++++++ builtin/mainmenu/fm_modmgr.lua | 1120 ++++++++++++++++ builtin/mainmenu/gamemgr.lua | 2 +- builtin/mainmenu/init_old.lua | 164 --- builtin/mainmenu/menubar.lua | 80 ++ builtin/mainmenu/modmgr.lua | 12 +- builtin/mainmenu/modstore.lua | 615 +++++++++ builtin/mainmenu/store.lua | 910 ++++++------- builtin/mainmenu/tab_credits.lua | 112 +- builtin/mainmenu/tab_help.lua | 59 + builtin/mainmenu/tab_mods.lua | 232 ++-- builtin/mainmenu/tab_multiplayer.lua | 466 ++++--- builtin/mainmenu/tab_server.lua | 347 +++-- builtin/mainmenu/tab_settings.lua | 672 +++++----- builtin/mainmenu/tab_simple_main.lua | 212 +-- builtin/mainmenu/tab_singleplayer.lua | 405 +++--- builtin/mainmenu/tab_texturepacks.lua | 158 +-- builtin/mainmenu/textures.lua | 226 ++-- builtin/profiler.lua | 66 + 58 files changed, 7559 insertions(+), 3255 deletions(-) delete mode 100644 build/android/libs/wversionmanager-1.2.jar create mode 100644 build/android/libs/wversionmanager-1.3.jar create mode 100644 builtin/ProFi.lua create mode 100644 builtin/game/mod_debugging.lua create mode 100644 builtin/game/stat.lua create mode 100644 builtin/key_value_storage.lua create mode 100644 builtin/mainmenu/dlg_add_server.lua create mode 100644 builtin/mainmenu/fm_gamemgr.lua rename builtin/mainmenu/{init.lua => fm_init.lua} (53%) create mode 100644 builtin/mainmenu/fm_init_orig.lua create mode 100644 builtin/mainmenu/fm_modmgr.lua delete mode 100644 builtin/mainmenu/init_old.lua create mode 100644 builtin/mainmenu/menubar.lua create mode 100644 builtin/mainmenu/modstore.lua create mode 100644 builtin/mainmenu/tab_help.lua create mode 100644 builtin/profiler.lua diff --git a/build/android/Makefile b/build/android/Makefile index 0c3ec2a1b..f979d2551 100644 --- a/build/android/Makefile +++ b/build/android/Makefile @@ -693,8 +693,8 @@ apk: $(PATHCFGFILE) assets $(IRRLICHT_LIB) $(CURL_LIB) $(LEVELDB_TARGET) \ TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" && \ ant $$BUILD_TYPE && \ echo "++ Success!" && \ - echo "APK: bin/Minetest-$$BUILD_TYPE.apk" && \ - echo "You can install it with \`adb install -r bin/Minetest-$$BUILD_TYPE.apk\`" + echo "APK: bin/MultiCraft-$$BUILD_TYPE.apk" && \ + echo "You can install it with \`adb install -r bin/MultiCraft-$$BUILD_TYPE.apk\`" prep_srcdir : @rm ${ROOT}/jni/src; \ @@ -704,14 +704,14 @@ clean_apk : manifest @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ export ANDROID_HOME=${SDKFOLDER}; \ ant clean - + install_debug : @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ - adb install -r ${ROOT}/bin/Minetest-debug.apk + adb install -r ${ROOT}/bin/MultiCraft-debug.apk install : @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ - adb install -r ${ROOT}/bin/Minetest-release.apk + adb install -r ${ROOT}/bin/MultiCraft-release.apk envpaths : @echo "export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}" > and_env;\ diff --git a/build/android/libs/wversionmanager-1.2.jar b/build/android/libs/wversionmanager-1.2.jar deleted file mode 100644 index 48bb8561f688d2e06fc3d579cae144fae9915401..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9956 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 diff --git a/build/android/libs/wversionmanager-1.3.jar b/build/android/libs/wversionmanager-1.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..390ce173ce07009054404f9cd08f303702ef7180 GIT binary patch literal 10769 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 0 or #self.memoryReports > 0 then + filename = filename or 'ProFi.txt' + self:sortReportsWithSortMethod( self.reports, self.sortMethod ) + self:writeReportsToFilename( filename ) + print( string.format("[ProFi]\t Report written to %s", filename) ) + end +end + +--[[ + Resets any profile information stored. +]] +function ProFi:reset() + self.reports = {} + self.reportsByTitle = {} + self.memoryReports = {} + self.highestMemoryReport = nil + self.lowestMemoryReport = nil + self.has_started = false + self.has_finished = false + self.should_run_once = false + self.lastCheckMemoryTime = nil + self.hookCount = self.hookCount or DEFAULT_DEBUG_HOOK_COUNT + self.sortMethod = self.sortMethod or sortByDurationDesc + self.inspect = nil +end + +--[[ + Set how often a hook is called. + See http://pgl.yoyo.org/luai/i/debug.sethook for information. + Param: [hookCount:number] if 0 ProFi counts every time a function is called. + if 2 ProFi counts every other 2 function calls. +]] +function ProFi:setHookCount( hookCount ) + self.hookCount = hookCount +end + +--[[ + Set how the report is sorted when written to file. + Param: [sortType:string] either 'duration' or 'count'. + 'duration' sorts by the time a method took to run. + 'count' sorts by the number of times a method was called. +]] +function ProFi:setSortMethod( sortType ) + if sortType == 'duration' then + self.sortMethod = sortByDurationDesc + elseif sortType == 'count' then + self.sortMethod = sortByCallCount + end +end + +--[[ + By default the getTime method is os.clock (CPU time), + If you wish to use other time methods pass it to this function. + Param: [getTimeMethod:function] +]] +function ProFi:setGetTimeMethod( getTimeMethod ) + getTime = getTimeMethod +end + +--[[ + Allows you to inspect a specific method. + Will write to the report a list of methods that + call this method you're inspecting, you can optionally + provide a levels parameter to traceback a number of levels. + Params: [methodName:string] the name of the method you wish to inspect. + [levels:number:optional] the amount of levels you wish to traceback, defaults to 1. +]] +function ProFi:setInspect( methodName, levels ) + if self.inspect then + self.inspect.methodName = methodName + self.inspect.levels = levels or 1 + else + self.inspect = { + ['methodName'] = methodName; + ['levels'] = levels or 1; + } + end +end + +----------------------- +-- Implementations methods: +----------------------- + +function ProFi:shouldReturn( ) + return self.should_run_once and self.has_finished +end + +function ProFi:getFuncReport( funcInfo ) + local title = self:getTitleFromFuncInfo( funcInfo ) + local funcReport = self.reportsByTitle[ title ] + if not funcReport then + funcReport = self:createFuncReport( funcInfo ) + self.reportsByTitle[ title ] = funcReport + table.insert( self.reports, funcReport ) + end + return funcReport +end + +function ProFi:getTitleFromFuncInfo( funcInfo ) + local name = funcInfo.name or 'anonymous' + -- TODO (freeminer): remove common path, i.e. /home/xyz/freeminer/games/default/, from the source + local source = funcInfo.source:sub(-50) or 'C_FUNC' + local linedefined = funcInfo.linedefined or 0 + linedefined = string.format( FORMAT_LINENUM, linedefined ) + return string.format(FORMAT_TITLE, source, name, linedefined) +end + +function ProFi:createFuncReport( funcInfo ) + local name = funcInfo.name or 'anonymous' + local source = funcInfo.source or 'C Func' + local linedefined = funcInfo.linedefined or 0 + local funcReport = { + ['title'] = self:getTitleFromFuncInfo( funcInfo ); + ['count'] = 0; + ['timer'] = 0; + } + return funcReport +end + +function ProFi:startHooks() + debug.sethook( onDebugHook, 'cr', self.hookCount ) +end + +function ProFi:stopHooks() + debug.sethook() +end + +function ProFi:sortReportsWithSortMethod( reports, sortMethod ) + if reports then + table.sort( reports, sortMethod ) + end +end + +function ProFi:writeReportsToFilename( filename ) + local file, err = io.open( filename, 'w' ) + assert( file, err ) + self:writeBannerToFile( file ) + if #self.reports > 0 then + self:writeProfilingReportsToFile( self.reports, file ) + end + if #self.memoryReports > 0 then + self:writeMemoryReportsToFile( self.memoryReports, file ) + end + file:close() +end + +function ProFi:writeProfilingReportsToFile( reports, file ) + local totalTime = self.stopTime - self.startTime + local totalTimeOutput = string.format(FORMAT_TOTALTIME_LINE, totalTime) + file:write( totalTimeOutput ) + local header = string.format( FORMAT_HEADER_LINE, "FILE", "FUNCTION", "LINE", "TIME", "RELATIVE", "CALLED" ) + file:write( header ) + for i, funcReport in ipairs( reports ) do + local timer = string.format(FORMAT_TIME, funcReport.timer) + local count = string.format(FORMAT_COUNT, funcReport.count) + local relTime = string.format(FORMAT_RELATIVE, (funcReport.timer / totalTime) * 100 ) + local outputLine = string.format(FORMAT_OUTPUT_LINE, funcReport.title, timer, relTime, count ) + file:write( outputLine ) + if funcReport.inspections then + self:writeInpsectionsToFile( funcReport.inspections, file ) + end + end +end + +function ProFi:writeMemoryReportsToFile( reports, file ) + file:write( FORMAT_MEMORY_HEADER1 ) + self:writeHighestMemoryReportToFile( file ) + self:writeLowestMemoryReportToFile( file ) + file:write( FORMAT_MEMORY_HEADER2 ) + for i, memoryReport in ipairs( reports ) do + local outputLine = self:formatMemoryReportWithFormatter( memoryReport, FORMAT_MEMORY_LINE ) + file:write( outputLine ) + end +end + +function ProFi:writeHighestMemoryReportToFile( file ) + local memoryReport = self.highestMemoryReport + local outputLine = self:formatMemoryReportWithFormatter( memoryReport, FORMAT_HIGH_MEMORY_LINE ) + file:write( outputLine ) +end + +function ProFi:writeLowestMemoryReportToFile( file ) + local memoryReport = self.lowestMemoryReport + local outputLine = self:formatMemoryReportWithFormatter( memoryReport, FORMAT_LOW_MEMORY_LINE ) + file:write( outputLine ) +end + +function ProFi:formatMemoryReportWithFormatter( memoryReport, formatter ) + local time = string.format(FORMAT_TIME, memoryReport.time) + local kbytes = string.format(FORMAT_KBYTES, memoryReport.memory) + local mbytes = string.format(FORMAT_MBYTES, memoryReport.memory/1024) + local outputLine = string.format(formatter, time, kbytes, mbytes, memoryReport.note) + return outputLine +end + +function ProFi:writeBannerToFile( file ) + local banner = string.format(FORMAT_BANNER, os.date()) + file:write( banner ) +end + +function ProFi:writeInpsectionsToFile( inspections, file ) + local inspectionsList = self:sortInspectionsIntoList( inspections ) + file:write('\n==^ INSPECT ^======================================================================================================== COUNT ===\n') + for i, inspection in ipairs( inspectionsList ) do + local line = string.format(FORMAT_LINENUM, inspection.line) + local title = string.format(FORMAT_TITLE, inspection.source, inspection.name, line) + local count = string.format(FORMAT_COUNT, inspection.count) + local outputLine = string.format(FORMAT_INSPECTION_LINE, title, count ) + file:write( outputLine ) + end + file:write('===============================================================================================================================\n\n') +end + +function ProFi:sortInspectionsIntoList( inspections ) + local inspectionsList = {} + for k, inspection in pairs(inspections) do + inspectionsList[#inspectionsList+1] = inspection + end + table.sort( inspectionsList, sortByCallCount ) + return inspectionsList +end + +function ProFi:resetReports( reports ) + for i, report in ipairs( reports ) do + report.timer = 0 + report.count = 0 + report.inspections = nil + end +end + +function ProFi:shouldInspect( funcInfo ) + return self.inspect and self.inspect.methodName == funcInfo.name +end + +function ProFi:getInspectionsFromReport( funcReport ) + local inspections = funcReport.inspections + if not inspections then + inspections = {} + funcReport.inspections = inspections + end + return inspections +end + +function ProFi:getInspectionWithKeyFromInspections( key, inspections ) + local inspection = inspections[key] + if not inspection then + inspection = { + ['count'] = 0; + } + inspections[key] = inspection + end + return inspection +end + +function ProFi:doInspection( inspect, funcReport ) + local inspections = self:getInspectionsFromReport( funcReport ) + local levels = 5 + inspect.levels + local currentLevel = 5 + while currentLevel < levels do + local funcInfo = debug.getinfo( currentLevel, 'nS' ) + if funcInfo then + local source = funcInfo.short_src or '[C]' + local name = funcInfo.name or 'anonymous' + local line = funcInfo.linedefined + local key = source..name..line + local inspection = self:getInspectionWithKeyFromInspections( key, inspections ) + inspection.source = source + inspection.name = name + inspection.line = line + inspection.count = inspection.count + 1 + currentLevel = currentLevel + 1 + else + break + end + end +end + +function ProFi:onFunctionCall( funcInfo ) + local funcReport = ProFi:getFuncReport( funcInfo ) + funcReport.callTime = getTime() + funcReport.count = funcReport.count + 1 + if self:shouldInspect( funcInfo ) then + self:doInspection( self.inspect, funcReport ) + end +end + +function ProFi:onFunctionReturn( funcInfo ) + local funcReport = ProFi:getFuncReport( funcInfo ) + if funcReport.callTime then + local time = getTime() - funcReport.callTime + -- handle overflow for unsigned 32-bit time + -- if for some reason `unsigned int` is 64-bit then overflows don't happen! + if time < 0 then + time = 4294967296 / 1000000 + time + end + funcReport.timer = funcReport.timer + time + end +end + +function ProFi:setHighestMemoryReport( memoryReport ) + if not self.highestMemoryReport then + self.highestMemoryReport = memoryReport + else + if memoryReport.memory > self.highestMemoryReport.memory then + self.highestMemoryReport = memoryReport + end + end +end + +function ProFi:setLowestMemoryReport( memoryReport ) + if not self.lowestMemoryReport then + self.lowestMemoryReport = memoryReport + else + if memoryReport.memory < self.lowestMemoryReport.memory then + self.lowestMemoryReport = memoryReport + end + end +end + +----------------------- +-- Local Functions: +----------------------- + +getTime = os.clock + +onDebugHook = function( hookType ) + local funcInfo = debug.getinfo( 2, 'nS' ) + if hookType == "call" then + ProFi:onFunctionCall( funcInfo ) + elseif hookType == "return" then + ProFi:onFunctionReturn( funcInfo ) + end +end + +sortByDurationDesc = function( a, b ) + return a.timer > b.timer +end + +sortByCallCount = function( a, b ) + return a.count > b.count +end + +----------------------- +-- Return Module: +----------------------- + +ProFi:reset() +return ProFi diff --git a/builtin/common/filterlist.lua b/builtin/common/filterlist.lua index ade96babb..210681133 100644 --- a/builtin/common/filterlist.lua +++ b/builtin/common/filterlist.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index c6b549028..3e6a5b775 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/misc_helpers.lua +-- Minetest: builtin/misc_helpers.lua -------------------------------------------------------------------------------- function basic_dump(o) @@ -441,6 +441,114 @@ if INIT == "game" then end +-------------------------------------------------------------------------------- +--Wrapper for rotate_and_place() to check for sneak and assume Creative mode +--implies infinite stacks when performing a 6d rotation. +-------------------------------------------------------------------------------- + + minetest.rotate_node = function(itemstack, placer, pointed_thing) + minetest.rotate_and_place(itemstack, placer, pointed_thing, + minetest.setting_getbool("creative_mode"), + {invert_wall = placer:get_player_control().sneak}) + return itemstack + end + +-------------------------------------------------------------------------------- +-- Function to make a copy of an existing node definition, to be used +-- by mods that need to redefine some aspect of a node, but without +-- them having to copy&paste the entire node definition. +-------------------------------------------------------------------------------- + + function minetest.clone_node(name) + node2={} + node=minetest.registered_nodes[name] + for k,v in pairs(node) do + node2[k]=v + end + return node2 + end + +end + +-------------------------------------------------------------------------------- + +if minetest then + local dirs1 = { 9, 18, 7, 12 } + local dirs2 = { 20, 23, 22, 21 } + + function minetest.rotate_and_place(itemstack, placer, pointed_thing, infinitestacks, orient_flags) + orient_flags = orient_flags or {} + + local node = minetest.get_node(pointed_thing.under) + if not minetest.registered_nodes[node.name] + or not minetest.registered_nodes[node.name].on_rightclick then + + local above = pointed_thing.above + local under = pointed_thing.under + local pitch = placer:get_look_pitch() + local pname = minetest.get_node(under).name + local node = minetest.get_node(above) + local fdir = minetest.dir_to_facedir(placer:get_look_dir()) + local wield_name = itemstack:get_name() + local reg_node = minetest.registered_nodes[pname] + + if not reg_node or not reg_node.on_rightclick then + + local iswall = (above.x ~= under.x) or (above.z ~= under.z) + local isceiling = (above.x == under.x) and (above.z == under.z) + and (pitch > 0) + local pos1 = above + + if reg_node and reg_node.buildable_to then + pos1 = under + iswall = false + end + + reg_node = minetest.registered_nodes[minetest.get_node(pos1).name] + if not reg_node or not reg_node.buildable_to then + return + end + + if orient_flags.force_floor then + iswall = false + isceiling = false + elseif orient_flags.force_ceiling then + iswall = false + isceiling = true + elseif orient_flags.force_wall then + iswall = true + isceiling = false + elseif orient_flags.invert_wall then + iswall = not iswall + end + + if iswall then + minetest.add_node(pos1, {name = wield_name, param2 = dirs1[fdir+1] }) + elseif isceiling then + if orient_flags.force_facedir then + minetest.add_node(pos1, {name = wield_name, param2 = 20 }) + else + minetest.add_node(pos1, {name = wield_name, param2 = dirs2[fdir+1] }) + end + else -- place right side up + if orient_flags.force_facedir then + minetest.add_node(pos1, {name = wield_name, param2 = 0 }) + else + minetest.add_node(pos1, {name = wield_name, param2 = fdir }) + end + end + + if not infinitestacks then + itemstack:take_item() + return itemstack + end + end + else + minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) + end + end + + -------------------------------------------------------------------------------- --Wrapper for rotate_and_place() to check for sneak and assume Creative mode --implies infinite stacks when performing a 6d rotation. @@ -593,4 +701,3 @@ if INIT == "mainmenu" then return core.formspec_escape(fgettext_ne(text, ...)) end end - diff --git a/builtin/common/serialize.lua b/builtin/common/serialize.lua index 90b8b2ad6..24b2a12ee 100644 --- a/builtin/common/serialize.lua +++ b/builtin/common/serialize.lua @@ -115,20 +115,11 @@ function core.serialize(x) function dump_val(x) local tp = type(x) if x == nil then return "nil" + elseif tp == "number" then return string.format("%d", x) elseif tp == "string" then return string.format("%q", x) elseif tp == "boolean" then return x and "true" or "false" elseif tp == "function" then return string.format("loadstring(%q)", string.dump(x)) - elseif tp == "number" then - -- Serialize integers with string.format to prevent - -- scientific notation, which doesn't preserve - -- precision and breaks things like node position - -- hashes. Serialize floats normally. - if math.floor(x) == x then - return string.format("%d", x) - else - return tostring(x) - end elseif tp == "table" then local vals = {} local idx_dumped = {} diff --git a/builtin/common/strict.lua b/builtin/common/strict.lua index c7b86461f..c353bb913 100644 --- a/builtin/common/strict.lua +++ b/builtin/common/strict.lua @@ -4,11 +4,6 @@ local WARN_INIT = false -function core.global_exists(name) - return rawget(_G, name) ~= nil -end - - local function warn(message) print(os.date("%H:%M:%S: WARNING: ")..message) end diff --git a/builtin/fstk/buttonbar.lua b/builtin/fstk/buttonbar.lua index 33d80e064..9a9ec999b 100644 --- a/builtin/fstk/buttonbar.lua +++ b/builtin/fstk/buttonbar.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --self program is free software; you can redistribute it and/or modify diff --git a/builtin/fstk/dialog.lua b/builtin/fstk/dialog.lua index f11bc2ad7..214b0388f 100644 --- a/builtin/fstk/dialog.lua +++ b/builtin/fstk/dialog.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --self program is free software; you can redistribute it and/or modify diff --git a/builtin/fstk/tabview.lua b/builtin/fstk/tabview.lua index e4ed248df..5050596ad 100644 --- a/builtin/fstk/tabview.lua +++ b/builtin/fstk/tabview.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --self program is free software; you can redistribute it and/or modify @@ -214,60 +214,60 @@ 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 + 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 + 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 = {} + 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 + 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) + setmetatable(self, tabview_metatable) - self.fixed_size = true - self.hidden = true - self.current_tab = nil - self.last_tab_index = 1 - self.tablist = {} + self.fixed_size = true + self.hidden = true + self.current_tab = nil + self.last_tab_index = 1 + self.tablist = {} + + self.autosave_tab = false - self.autosave_tab = false - - ui.add(self) - return self + ui.add(self) + return self end diff --git a/builtin/fstk/ui.lua b/builtin/fstk/ui.lua index 055772a13..75b3fec0e 100644 --- a/builtin/fstk/ui.lua +++ b/builtin/fstk/ui.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --self program is free software; you can redistribute it and/or modify @@ -109,7 +109,7 @@ function ui.handle_buttons(fields) if fields["btn_error_confirm"] then gamedata.errormessage = nil - update_menu() + menu.update() return end diff --git a/builtin/game/auth.lua b/builtin/game/auth.lua index ac6f96616..73a5f9748 100644 --- a/builtin/game/auth.lua +++ b/builtin/game/auth.lua @@ -1,11 +1,11 @@ --- multicraft: builtin/auth.lua +-- Minetest: builtin/auth.lua -- -- Authentication handler -- function core.string_to_privs(str, delim) - assert(type(str) == "string") + if type(str) ~= "string" then return end delim = delim or ',' local privs = {} for _, priv in pairs(string.split(str, delim)) do @@ -32,6 +32,23 @@ assert(core.privs_to_string({a=true,b=true}) == "a,b") core.auth_file_path = core.get_worldpath().."/auth.txt" core.auth_table = {} +local hex={} +for i=0,255 do + hex[string.format("%0x",i)]=string.char(i) + hex[string.format("%0X",i)]=string.char(i) +end + +local function uri_decode(str) + str = string.gsub (str, "+", " ") + return (str:gsub('%%(%x%x)',hex)) +end + +function uri_encode (str) + str = string.gsub (str, "([^0-9a-zA-Z_ -])", function (c) return string.format ("%%%02X", string.byte(c)) end) + str = string.gsub (str, " ", "+") + return str +end + local function read_auth_file() local newtable = {} local file, errmsg = io.open(core.auth_file_path, 'rb') @@ -48,7 +65,7 @@ local function read_auth_file() error("Invalid line in auth.txt: "..dump(line)) end local privileges = core.string_to_privs(privilege_string) - newtable[name] = {password=password, privileges=privileges, last_login=last_login} + newtable[uri_decode(name)] = {password=password, privileges=privileges, last_login=last_login} end end io.close(file) @@ -73,7 +90,7 @@ local function save_auth_file() end for name, stuff in pairs(core.auth_table) do local priv_string = core.privs_to_string(stuff.privileges) - local parts = {name, stuff.password, priv_string, stuff.last_login or ""} + local parts = {uri_encode(name), stuff.password, priv_string, stuff.last_login or ""} file:write(table.concat(parts, ":").."\n") end io.close(file) @@ -123,9 +140,13 @@ core.builtin_auth_handler = { assert(type(name) == "string") assert(type(password) == "string") core.log('info', "Built-in authentication handler adding player '"..name.."'") + local privs = core.setting_get("default_privs") + if core.setting_getbool("creative_mode") and core.setting_get("default_privs_creative") then + privs = core.setting_get("default_privs_creative") + end core.auth_table[name] = { password = password, - privileges = core.string_to_privs(core.setting_get("default_privs")), + privileges = core.string_to_privs(privs), last_login = os.time(), } save_auth_file() diff --git a/builtin/game/chatcommands.lua b/builtin/game/chatcommands.lua index dba0c81be..9b3d3ef01 100644 --- a/builtin/game/chatcommands.lua +++ b/builtin/game/chatcommands.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/chatcommands.lua +-- Minetest: builtin/chatcommands.lua -- -- Chat command handler @@ -67,9 +67,10 @@ core.register_chatcommand("help", { description = "Get help for commands or list privileges", func = function(name, param) local function format_help_line(cmd, def) + local msg = freeminer.colorize("00ffff", "/"..cmd) local msg = "/"..cmd if def.params and def.params ~= "" then - msg = msg .. " " .. def.params + msg = msg .. " " .. freeminer.colorize("eeeeee", def.params) end if def.description and def.description ~= "" then msg = msg .. ": " .. def.description @@ -229,28 +230,21 @@ core.register_chatcommand("setpassword", { if not toname then return false, "Name field required" end - local act_str_past = "?" - local act_str_pres = "?" + local actstr = "?" if not raw_password then core.set_player_password(toname, "") - act_str_past = "cleared" - act_str_pres = "clears" + actstr = "cleared" else core.set_player_password(toname, core.get_password_hash(toname, raw_password)) - act_str_past = "set" - act_str_pres = "sets" + actstr = "set" end if toname ~= name then core.chat_send_player(toname, "Your password was " - .. act_str_past .. " by " .. name) + .. actstr .. " by " .. name) end - - core.log("action", name .. " " .. act_str_pres - .. " password of " .. toname .. ".") - - return true, "Password of player \"" .. toname .. "\" " .. act_str_past + return true, "Password of player \"" .. toname .. "\" " .. actstr end, }) @@ -264,9 +258,6 @@ core.register_chatcommand("clearpassword", { return false, "Name field required" end core.set_player_password(toname, '') - - core.log("action", name .. " clears password of " .. toname .. ".") - return true, "Password of player \"" .. toname .. "\" cleared" end, }) @@ -414,14 +405,13 @@ core.register_chatcommand("set", { }) core.register_chatcommand("deleteblocks", { - params = "(here [radius]) | ( )", + params = "[here] [ ]", description = "delete map blocks contained in area pos1 to pos2", privs = {server=true}, func = function(name, param) local p1 = {} local p2 = {} - local args = param:split(" ") - if args[1] == "here" then + if param == "here" then local player = core.get_player_by_name(name) if player == nil then core.log("error", "player is nil") @@ -429,12 +419,6 @@ core.register_chatcommand("deleteblocks", { end p1 = player:getpos() p2 = p1 - - if #args >= 2 then - local radius = tonumber(args[2]) or 0 - p1 = vector.add(p1, radius) - p2 = vector.subtract(p2, radius) - end else local pos1, pos2 = unpack(param:split(") (")) if pos1 == nil or pos2 == nil then @@ -525,6 +509,7 @@ core.register_chatcommand("giveme", { if not itemstring then return false, "ItemString required" end + core.stat_add("giveme", name) return handle_give_command("/giveme", name, name, itemstring) end, }) @@ -749,11 +734,7 @@ core.register_chatcommand("kick", { if not core.kick_player(tokick, reason) then return false, "Failed to kick player " .. tokick end - local log_reason = "" - if reason then - log_reason = " with reason \"" .. reason .. "\"" - end - core.log("action", name .. " kicks " .. tokick .. log_reason) + core.log("action", name .. " kicked " .. tokick) return true, "Kicked " .. tokick end, }) @@ -793,6 +774,19 @@ core.register_chatcommand("msg", { end, }) +core.register_chatcommand("die", { + params = "", + description = "Kills yourself.", + func = function(name, param) + local player = core.get_player_by_name(name) + if not player then + return + end + player:set_hp(0) + core.stat_add("suicide", name) + end, +}) + core.register_chatcommand("last-login", { params = "[name]", description = "Get the last login time of a player", @@ -810,3 +804,16 @@ core.register_chatcommand("last-login", { end, }) +core.register_chatcommand( "stat", { + params = "[name]", + description = "show in-game action statistics", + func = function(name, param) + if param == "" then + param = name + elseif not core.get_player_by_name(param) then + return false, "No such player." + end + local formspec = core.stat_formspec(param) + core.show_formspec(name, 'stat', formspec) + end +}) diff --git a/builtin/game/deprecated.lua b/builtin/game/deprecated.lua index 45c4f19ff..bbe68be3e 100644 --- a/builtin/game/deprecated.lua +++ b/builtin/game/deprecated.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/deprecated.lua +-- Minetest: builtin/deprecated.lua -- -- Default material types diff --git a/builtin/game/detached_inventory.lua b/builtin/game/detached_inventory.lua index 1628e3f49..e8f03b56c 100644 --- a/builtin/game/detached_inventory.lua +++ b/builtin/game/detached_inventory.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/detached_inventory.lua +-- Minetest: builtin/detached_inventory.lua core.detached_inventories = {} diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index 7b55a0a43..5945e7f7b 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -1,9 +1,34 @@ --- multicraft: builtin/item.lua +-- Minetest: builtin/item.lua -- -- Falling stuff -- +function node_drop(np, remove_fast) + local n2 = minetest.get_node(np) + -- If it's not air or liquid, remove node and replace it with + -- it's drops + if n2.name ~= "air" and (not core.registered_nodes[n2.name] or + core.registered_nodes[n2.name].liquidtype == "none") then + core.remove_node(np, remove_fast) + if core.registered_nodes[n2.name].buildable_to == false then + -- Add dropped items + local drops = core.get_node_drops(n2.name, "") + local _, dropped_item + for _, dropped_item in ipairs(drops) do + core.add_item(np, dropped_item) + end + end + -- Run script hook + local _, callback + for _, callback in ipairs(core.registered_on_dignodes) do + callback(np, n2, nil) + end + end +end + +local remove_fast = 0 + core.register_entity(":__builtin:falling_node", { initial_properties = { physical = true, @@ -47,6 +72,7 @@ core.register_entity(":__builtin:falling_node", { end, on_step = function(self, dtime) + if dtime > 0.2 then remove_fast = 2 else remove_fast = 0 end -- Set gravity self.object:setacceleration({x=0, y=-10, z=0}) -- Turn to actual sand when collides to ground or just move @@ -59,7 +85,7 @@ core.register_entity(":__builtin:falling_node", { (bcd.walkable or (core.get_item_group(self.node.name, "float") ~= 0 and bcd.liquidtype ~= "none")) then - if bcd and bcd.leveled and + if bcd and bcd.leveled and bcd.leveled > 0 and bcn.name == self.node.name then local addlevel = self.node.level if addlevel == nil or addlevel <= 0 then @@ -72,31 +98,14 @@ core.register_entity(":__builtin:falling_node", { elseif bcd and bcd.buildable_to and (core.get_item_group(self.node.name, "float") == 0 or bcd.liquidtype == "none") then - core.remove_node(bcp) + core.remove_node(bcp, remove_fast) return end local np = {x=bcp.x, y=bcp.y+1, z=bcp.z} -- Check what's here local n2 = core.get_node(np) - -- If it's not air or liquid, remove node and replace it with - -- it's drops - if n2.name ~= "air" and (not core.registered_nodes[n2.name] or - core.registered_nodes[n2.name].liquidtype == "none") then - core.remove_node(np) - if core.registered_nodes[n2.name].buildable_to == false then - -- Add dropped items - local drops = core.get_node_drops(n2.name, "") - local _, dropped_item - for _, dropped_item in ipairs(drops) do - core.add_item(np, dropped_item) - end - end - -- Run script hook - local _, callback - for _, callback in ipairs(core.registered_on_dignodes) do - callback(np, n2, nil) - end - end + -- remove node and replace it with it's drops + node_drop(np, remove_fast) -- Create node and remove entity core.add_node(np, self.node) self.object:remove() @@ -113,12 +122,13 @@ core.register_entity(":__builtin:falling_node", { function spawn_falling_node(p, node) local obj = core.add_entity(p, "__builtin:falling_node") + if not obj then return end obj:get_luaentity():set_node(node) end function drop_attached_node(p) local nn = core.get_node(p).name - core.remove_node(p) + core.remove_node(p, remove_fast) for _,item in ipairs(core.get_node_drops(nn, "")) do local pos = { x = p.x + math.random()/2 - 0.25, @@ -179,7 +189,7 @@ function nodeupdate_single(p, delay) core.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false) else n.level = core.get_node_level(p) - core.remove_node(p) + core.remove_node(p, remove_fast) spawn_falling_node(p, n) nodeupdate(p) end diff --git a/builtin/game/features.lua b/builtin/game/features.lua index 2e79f9a66..f082b0db8 100644 --- a/builtin/game/features.lua +++ b/builtin/game/features.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/features.lua +-- Minetest: builtin/features.lua core.features = { glasslike_framed = true, diff --git a/builtin/game/init.lua b/builtin/game/init.lua index 24acd2e18..89574deeb 100644 --- a/builtin/game/init.lua +++ b/builtin/game/init.lua @@ -1,5 +1,5 @@ -local scriptpath = multicraft.get_builtin_path()..DIR_DELIM +local scriptpath = minetest.get_builtin_path()..DIR_DELIM local commonpath = scriptpath.."common"..DIR_DELIM local gamepath = scriptpath.."game"..DIR_DELIM @@ -17,6 +17,7 @@ dofile(gamepath.."deprecated.lua") dofile(gamepath.."misc.lua") dofile(gamepath.."privileges.lua") dofile(gamepath.."auth.lua") +dofile(gamepath.."stat.lua") dofile(gamepath.."chatcommands.lua") dofile(gamepath.."static_spawn.lua") dofile(gamepath.."detached_inventory.lua") @@ -26,3 +27,6 @@ dofile(gamepath.."voxelarea.lua") dofile(gamepath.."forceloading.lua") dofile(gamepath.."statbars.lua") +if core.setting_getbool("mod_debugging") then + dofile(gamepath.."mod_debugging.lua") +end diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 576b48887..cf6119854 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/item.lua +-- Minetest: builtin/item.lua local function copy_pointed_thing(pointed_thing) return { @@ -106,7 +106,7 @@ function core.facedir_to_dir(facedir) {x=0, y=1, z=0}}) --indexed into by a table of correlating facedirs - [({[0]=1, 2, 3, 4, + [({[0]=1, 2, 3, 4, 5, 2, 6, 4, 6, 2, 5, 4, 1, 5, 3, 6, @@ -238,7 +238,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2) core.log("action", placer:get_player_name() .. " places node " .. def.name .. " at " .. core.pos_to_string(place_to)) - + local oldnode = core.get_node(place_to) local newnode = {name = def.name, param1 = 0, param2 = param2} @@ -273,7 +273,13 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2) end -- Add node and update - core.add_node(place_to, newnode) + local olddef = core.registered_nodes[oldnode.name] + if olddef.leveled and olddef.leveled>0 and olddef.liquidtype ~= "none" and + (newnode.name == oldnode.name or newnode.name == olddef.liquid_alternative_flowing or newnode.name == olddef.liquid_alternative_source) then + core.add_node_level(place_to, olddef.leveled) + else + core.add_node(place_to, newnode) + end local take_item = true @@ -357,37 +363,19 @@ function core.item_drop(itemstack, dropper, pos) return itemstack end -function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing) - for _, callback in pairs(core.registered_on_item_eats) do - local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing) - if result then - return result - end - end - if itemstack:take_item() ~= nil then - user:set_hp(user:get_hp() + hp_change) - - if replace_with_item then - if itemstack:is_empty() then - itemstack:add_item(replace_with_item) - else - local inv = user:get_inventory() - if inv:room_for_item("main", {name=replace_with_item}) then - inv:add_item("main", replace_with_item) - else - local pos = user:getpos() - pos.y = math.floor(pos.y + 0.5) - core.add_item(pos, replace_with_item) - end - end - end - end - return itemstack -end - function core.item_eat(hp_change, replace_with_item) return function(itemstack, user, pointed_thing) -- closure - return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing) + for _, callback in pairs(core.registered_on_item_eats) do + local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing) + if result then + return result + end + end + if itemstack:take_item() ~= nil then + user:set_hp(user:get_hp() + hp_change) + itemstack:add_item(replace_with_item) -- note: replace_with_item is optional + end + return itemstack end end @@ -443,7 +431,7 @@ function core.node_dig(pos, node, digger) local wielded = digger:get_wielded_item() local drops = core.get_node_drops(node.name, wielded:get_name()) - + local wdef = wielded:get_definition() local tp = wielded:get_tool_capabilities() local dp = core.get_dig_params(def.groups, tp) @@ -456,7 +444,7 @@ function core.node_dig(pos, node, digger) end end digger:set_wielded_item(wielded) - + -- Handle drops core.handle_node_drops(pos, drops, digger) @@ -467,7 +455,7 @@ function core.node_dig(pos, node, digger) -- Remove node and update core.remove_node(pos) - + -- Run callback if def.after_dig_node then -- Copy pos and node because callback can modify them @@ -525,7 +513,7 @@ core.nodedef_default = { on_dig = redef_wrapper(core, 'node_dig'), -- core.node_dig on_receive_fields = nil, - + on_metadata_inventory_move = core.node_metadata_inventory_move_allow_all, on_metadata_inventory_offer = core.node_metadata_inventory_offer_allow_all, on_metadata_inventory_take = core.node_metadata_inventory_take_allow_all, diff --git a/builtin/game/item_entity.lua b/builtin/game/item_entity.lua index 88f6a4ad1..f9eb93184 100644 --- a/builtin/game/item_entity.lua +++ b/builtin/game/item_entity.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/item_entity.lua +-- Minetest: builtin/item_entity.lua function core.spawn_item(pos, item) -- Take item in any format @@ -13,7 +13,7 @@ end local time_to_live = tonumber(core.setting_get("item_entity_ttl")) if not time_to_live then - time_to_live = 900 + time_to_live = -1 end core.register_entity(":__builtin:item", { @@ -108,7 +108,7 @@ core.register_entity(":__builtin:item", { local nn = core.get_node(p).name -- If node is not registered or node is walkably solid and resting on nodebox local v = self.object:getvelocity() - if not core.registered_nodes[nn] or core.registered_nodes[nn].walkable and v.y == 0 then + if not core.registered_nodes[nn] or (core.registered_nodes[nn].walkable and core.get_item_group(nn, "slippery")==0) and v.y == 0 then if self.physical_state then local own_stack = ItemStack(self.object:get_luaentity().itemstring) for _,object in ipairs(core.get_objects_inside_radius(p, 0.8)) do @@ -171,6 +171,17 @@ core.register_entity(":__builtin:item", { self.object:setacceleration({x = 0, y = -10, z = 0}) self.physical_state = true self.object:set_properties({physical = true}) + elseif core.get_item_group(nn, "slippery") ~= 0 then + if math.abs(v.x) < .2 and math.abs(v.z) < .2 then + self.object:setvelocity({x=0,y=0,z=0}) + self.object:setacceleration({x=0, y=0, z=0}) + self.physical_state = false + self.object:set_properties({ + physical = false + }) + else + self.object:setacceleration({x=-v.x, y=-10, z=-v.z}) + end end end end, diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua index c4b8d0881..010974b0e 100644 --- a/builtin/game/misc.lua +++ b/builtin/game/misc.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/misc.lua +-- Minetest: builtin/misc.lua -- -- Misc. API functions @@ -11,6 +11,7 @@ core.register_globalstep(function(dtime) table.insert(core.timers, timer) end core.timers_to_add = {} + local end_ms = os.clock() * 1000 + 50 local index = 1 while index <= #core.timers do local timer = core.timers[index] @@ -21,6 +22,7 @@ core.register_globalstep(function(dtime) else index = index + 1 end + if os.clock() * 1000 > end_ms then return end end end) @@ -60,8 +62,8 @@ function core.get_connected_players() local temp_table = {} for index, value in pairs(player_list) do if value:is_player_connected() then - table.insert(temp_table, value) - end + table.insert(temp_table, value) + end end return temp_table end @@ -112,3 +114,11 @@ function core.record_protection_violation(pos, name) end end +function freeminer.color(color) + assert(#color == 6, "Color must be six characters in length.") + return "\v" .. color +end + +function freeminer.colorize(color, message) + return freeminer.color(color) .. message .. freeminer.color("ffffff") +end diff --git a/builtin/game/mod_debugging.lua b/builtin/game/mod_debugging.lua new file mode 100644 index 000000000..e32f64058 --- /dev/null +++ b/builtin/game/mod_debugging.lua @@ -0,0 +1,126 @@ +-- Freeminer: builtin/game/mod_debugging.lua +-- by rubenwardy + +local mod = {} +mod.recipes = {} +mod.aliases = {} + +core.log("action", 'Mod debugging enabled') +-- Sees if there is a node with this group/these groups +-- Supports AND view group:name, name +local function group_exists(groupname) + local flags = groupname:split(",") + for name, def in pairs(core.registered_items) do + local flag = true + for k, v in pairs(flags) do + local g = def.groups and def.groups[v:gsub('%group:', '')] or 0 + if not g or g <= 0 then + flag = false + break + end + end + if flag then + return true + end + end + return false +end + +-- Check that the item exists +function mod.assert(recipe, _name, output) + local name = mod.strip_name(_name) + if name == nil then + core.log('error', 'nil in recipe for '..mod.strip_name(output)) + print(recipe.from) + return + end + + if mod.aliases[name] ~= nil then + name = mod.aliases[name] + end + + if core.registered_items[name] == nil and not group_exists(name) then + core.log( 'error', 'missing item '..name.." in recipe for "..mod.strip_name(output) ) + print(recipe.from) + end +end + +-- Turns a itemstack name into just its item name +-- For example: "mod:item 99" -> "mod:item" +function mod.strip_name(name) + if name == nil then + return + end + + res = name:gsub('%"', '') + + if res:sub(1, 1) == ":" then + res = table.concat{res:sub(1, 1-1), "", res:sub(1+1)} + end + + for str in string.gmatch(res, "([^ ]+)") do + if str ~= " " and str ~= nil then + res=str + break + end + end + + if res == nil then + res="" + end + + return res +end + +-- Cycles through the recipe table, checking the items. +-- Recursive +function mod.check_recipe(recipe, table, output) + if type(table) == "table" then + for i=1,# table do + mod.check_recipe(recipe, table[i], output) + end + else + mod.assert(recipe, table,output) + end +end + +-- Check recipes once the game has loaded +core.after(0, function() +for i=1, #mod.recipes do + if mod.recipes[i] and mod.recipes[i].output then + mod.assert(mod.recipes[i], mod.recipes[i].output, mod.recipes[i].output) + + if type(mod.recipes[i].recipe) == "table" then + for a=1,# mod.recipes[i].recipe do + mod.check_recipe(mod.recipes[i], mod.recipes[i].recipe[a], mod.recipes[i].output) + end + else + mod.assert(mod.recipes[i], mod.recipes[i].recipe, mod.recipes[i].output) + end + end +end +end) + +-- Override register_craft to catch craft recipes +local register_craft = core.register_craft +core.register_craft = function(recipe) + register_craft(recipe) + + local name = mod.strip_name(recipe.output) + recipe.from = debug.traceback() + if name~=nil then + table.insert(mod.recipes, recipe) + end +end + +-- Override register_alias to catch aliases +local register_alias = core.register_alias +core.register_alias = function(new, old) + register_alias(new, old) + + local name = mod.strip_name(new) + local name2 = mod.strip_name(old) + if name~=nil and name2~=nil then + mod.aliases[new] = old + end +end diff --git a/builtin/game/mod_profiling.lua b/builtin/game/mod_profiling.lua index 6574cd676..df2d10221 100644 --- a/builtin/game/mod_profiling.lua +++ b/builtin/game/mod_profiling.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/game/mod_profiling.lua +-- Minetest: builtin/game/mod_profiling.lua local mod_statistics = {} mod_statistics.step_total = 0 diff --git a/builtin/game/privileges.lua b/builtin/game/privileges.lua index 990832094..7e6387c72 100644 --- a/builtin/game/privileges.lua +++ b/builtin/game/privileges.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/privileges.lua +-- Minetest: builtin/privileges.lua -- -- Privileges diff --git a/builtin/game/register.lua b/builtin/game/register.lua index 5442e1bb9..5bc14d07c 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/misc_register.lua +-- Minetest: builtin/misc_register.lua -- -- Make raw registration functions inaccessible to anyone except this file @@ -25,9 +25,9 @@ core.registered_aliases = {} -- For tables that are indexed by item name: -- If table[X] does not exist, default to table[core.registered_aliases[X]] local alias_metatable = { - __index = function(t, name) - return rawget(t, core.registered_aliases[name]) - end + __index = function(t, name) + return rawget(t, core.registered_aliases[name]) + end } setmetatable(core.registered_items, alias_metatable) setmetatable(core.registered_nodes, alias_metatable) @@ -37,215 +37,215 @@ setmetatable(core.registered_tools, alias_metatable) -- These item names may not be used because they would interfere -- with legacy itemstrings local forbidden_item_names = { - MaterialItem = true, - MaterialItem2 = true, - MaterialItem3 = true, - NodeItem = true, - node = true, - CraftItem = true, - craft = true, - MBOItem = true, - ToolItem = true, - tool = true, + MaterialItem = true, + MaterialItem2 = true, + MaterialItem3 = true, + NodeItem = true, + node = true, + CraftItem = true, + craft = true, + MBOItem = true, + ToolItem = true, + tool = true, } local function check_modname_prefix(name) - if name:sub(1,1) == ":" then - -- Escape the modname prefix enforcement mechanism - return name:sub(2) - else - -- Modname prefix enforcement - local expected_prefix = core.get_current_modname() .. ":" - if name:sub(1, #expected_prefix) ~= expected_prefix then - error("Name " .. name .. " does not follow naming conventions: " .. - "\"modname:\" or \":\" prefix required") - end - local subname = name:sub(#expected_prefix+1) - if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then - error("Name " .. name .. " does not follow naming conventions: " .. - "contains unallowed characters") - end - return name - end + if name:sub(1,1) == ":" then + -- Escape the modname prefix enforcement mechanism + return name:sub(2) + else + -- Modname prefix enforcement + local expected_prefix = core.get_current_modname() .. ":" + if name:sub(1, #expected_prefix) ~= expected_prefix then + error("Name " .. name .. " does not follow naming conventions: " .. + "\"modname:\" or \":\" prefix required") + end + local subname = name:sub(#expected_prefix+1) + if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then + error("Name " .. name .. " does not follow naming conventions: " .. + "contains unallowed characters") + end + return name + end end function core.register_abm(spec) - -- Add to core.registered_abms - core.registered_abms[#core.registered_abms+1] = spec + -- Add to core.registered_abms + core.registered_abms[#core.registered_abms+1] = spec end function core.register_entity(name, prototype) - -- Check name - if name == nil then - error("Unable to register entity: Name is nil") - end - name = check_modname_prefix(tostring(name)) + -- Check name + if name == nil then + error("Unable to register entity: Name is nil") + end + name = check_modname_prefix(tostring(name)) - prototype.name = name - prototype.__index = prototype -- so that it can be used as a metatable + prototype.name = name + prototype.__index = prototype -- so that it can be used as a metatable - -- Add to core.registered_entities - core.registered_entities[name] = prototype + -- Add to core.registered_entities + core.registered_entities[name] = prototype end function core.register_item(name, itemdef) - -- Check name - if name == nil then - error("Unable to register item: Name is nil") - end - name = check_modname_prefix(tostring(name)) - if forbidden_item_names[name] then - error("Unable to register item: Name is forbidden: " .. name) - end - itemdef.name = name + -- Check name + if name == nil then + error("Unable to register item: Name is nil") + end + name = check_modname_prefix(tostring(name)) + if forbidden_item_names[name] then + error("Unable to register item: Name is forbidden: " .. name) + end + itemdef.name = name - -- Apply defaults and add to registered_* table - if itemdef.type == "node" then - -- Use the nodebox as selection box if it's not set manually - if itemdef.drawtype == "nodebox" and not itemdef.selection_box then - itemdef.selection_box = itemdef.node_box - elseif itemdef.drawtype == "fencelike" and not itemdef.selection_box then - itemdef.selection_box = { - type = "fixed", - fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8}, - } - end - setmetatable(itemdef, {__index = core.nodedef_default}) - core.registered_nodes[itemdef.name] = itemdef - elseif itemdef.type == "craft" then - setmetatable(itemdef, {__index = core.craftitemdef_default}) - core.registered_craftitems[itemdef.name] = itemdef - elseif itemdef.type == "tool" then - setmetatable(itemdef, {__index = core.tooldef_default}) - core.registered_tools[itemdef.name] = itemdef - elseif itemdef.type == "none" then - setmetatable(itemdef, {__index = core.noneitemdef_default}) - else - error("Unable to register item: Type is invalid: " .. dump(itemdef)) - end + -- Apply defaults and add to registered_* table + if itemdef.type == "node" then + -- Use the nodebox as selection box if it's not set manually + if itemdef.drawtype == "nodebox" and not itemdef.selection_box then + itemdef.selection_box = itemdef.node_box + elseif itemdef.drawtype == "fencelike" and not itemdef.selection_box then + itemdef.selection_box = { + type = "fixed", + fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8}, + } + end + setmetatable(itemdef, {__index = core.nodedef_default}) + core.registered_nodes[itemdef.name] = itemdef + elseif itemdef.type == "craft" then + setmetatable(itemdef, {__index = core.craftitemdef_default}) + core.registered_craftitems[itemdef.name] = itemdef + elseif itemdef.type == "tool" then + setmetatable(itemdef, {__index = core.tooldef_default}) + core.registered_tools[itemdef.name] = itemdef + elseif itemdef.type == "none" then + setmetatable(itemdef, {__index = core.noneitemdef_default}) + else + error("Unable to register item: Type is invalid: " .. dump(itemdef)) + end - -- Flowing liquid uses param2 - if itemdef.type == "node" and itemdef.liquidtype == "flowing" then - itemdef.paramtype2 = "flowingliquid" - end + -- Flowing liquid uses param2 + if itemdef.type == "node" and itemdef.liquidtype == "flowing" and itemdef.paramtype2 == nil then + itemdef.paramtype2 = "flowingliquid" + end - -- BEGIN Legacy stuff - if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then - core.register_craft({ - type="cooking", - output=itemdef.cookresult_itemstring, - recipe=itemdef.name, - cooktime=itemdef.furnace_cooktime - }) - end - if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then - core.register_craft({ - type="fuel", - recipe=itemdef.name, - burntime=itemdef.furnace_burntime - }) - end - -- END Legacy stuff + -- BEGIN Legacy stuff + if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then + core.register_craft({ + type="cooking", + output=itemdef.cookresult_itemstring, + recipe=itemdef.name, + cooktime=itemdef.furnace_cooktime + }) + end + if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then + core.register_craft({ + type="fuel", + recipe=itemdef.name, + burntime=itemdef.furnace_burntime + }) + end + -- END Legacy stuff - -- Disable all further modifications - getmetatable(itemdef).__newindex = {} + -- Disable all further modifications + getmetatable(itemdef).__newindex = {} - --core.log("Registering item: " .. itemdef.name) - core.registered_items[itemdef.name] = itemdef - core.registered_aliases[itemdef.name] = nil - register_item_raw(itemdef) + --core.log("Registering item: " .. itemdef.name) + core.registered_items[itemdef.name] = itemdef + core.registered_aliases[itemdef.name] = nil + register_item_raw(itemdef) end function core.register_node(name, nodedef) - nodedef.type = "node" - core.register_item(name, nodedef) + nodedef.type = "node" + core.register_item(name, nodedef) end function core.register_craftitem(name, craftitemdef) - craftitemdef.type = "craft" + craftitemdef.type = "craft" - -- BEGIN Legacy stuff - if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then - craftitemdef.inventory_image = craftitemdef.image - end - -- END Legacy stuff + -- BEGIN Legacy stuff + if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then + craftitemdef.inventory_image = craftitemdef.image + end + -- END Legacy stuff - core.register_item(name, craftitemdef) + core.register_item(name, craftitemdef) end function core.register_tool(name, tooldef) - tooldef.type = "tool" - tooldef.stack_max = 1 + tooldef.type = "tool" + tooldef.stack_max = 1 - -- BEGIN Legacy stuff - if tooldef.inventory_image == nil and tooldef.image ~= nil then - tooldef.inventory_image = tooldef.image - end - if tooldef.tool_capabilities == nil and - (tooldef.full_punch_interval ~= nil or - tooldef.basetime ~= nil or - tooldef.dt_weight ~= nil or - tooldef.dt_crackiness ~= nil or - tooldef.dt_crumbliness ~= nil or - tooldef.dt_cuttability ~= nil or - tooldef.basedurability ~= nil or - tooldef.dd_weight ~= nil or - tooldef.dd_crackiness ~= nil or - tooldef.dd_crumbliness ~= nil or - tooldef.dd_cuttability ~= nil) then - tooldef.tool_capabilities = { - full_punch_interval = tooldef.full_punch_interval, - basetime = tooldef.basetime, - dt_weight = tooldef.dt_weight, - dt_crackiness = tooldef.dt_crackiness, - dt_crumbliness = tooldef.dt_crumbliness, - dt_cuttability = tooldef.dt_cuttability, - basedurability = tooldef.basedurability, - dd_weight = tooldef.dd_weight, - dd_crackiness = tooldef.dd_crackiness, - dd_crumbliness = tooldef.dd_crumbliness, - dd_cuttability = tooldef.dd_cuttability, - } - end - -- END Legacy stuff + -- BEGIN Legacy stuff + if tooldef.inventory_image == nil and tooldef.image ~= nil then + tooldef.inventory_image = tooldef.image + end + if tooldef.tool_capabilities == nil and + (tooldef.full_punch_interval ~= nil or + tooldef.basetime ~= nil or + tooldef.dt_weight ~= nil or + tooldef.dt_crackiness ~= nil or + tooldef.dt_crumbliness ~= nil or + tooldef.dt_cuttability ~= nil or + tooldef.basedurability ~= nil or + tooldef.dd_weight ~= nil or + tooldef.dd_crackiness ~= nil or + tooldef.dd_crumbliness ~= nil or + tooldef.dd_cuttability ~= nil) then + tooldef.tool_capabilities = { + full_punch_interval = tooldef.full_punch_interval, + basetime = tooldef.basetime, + dt_weight = tooldef.dt_weight, + dt_crackiness = tooldef.dt_crackiness, + dt_crumbliness = tooldef.dt_crumbliness, + dt_cuttability = tooldef.dt_cuttability, + basedurability = tooldef.basedurability, + dd_weight = tooldef.dd_weight, + dd_crackiness = tooldef.dd_crackiness, + dd_crumbliness = tooldef.dd_crumbliness, + dd_cuttability = tooldef.dd_cuttability, + } + end + -- END Legacy stuff - core.register_item(name, tooldef) + core.register_item(name, tooldef) end function core.register_alias(name, convert_to) - if forbidden_item_names[name] then - error("Unable to register alias: Name is forbidden: " .. name) - end - if core.registered_items[name] ~= nil then - core.log("WARNING: Not registering alias, item with same name" .. - " is already defined: " .. name .. " -> " .. convert_to) - else - --core.log("Registering alias: " .. name .. " -> " .. convert_to) - core.registered_aliases[name] = convert_to - register_alias_raw(name, convert_to) - end + if forbidden_item_names[name] then + error("Unable to register alias: Name is forbidden: " .. name) + end + if core.registered_items[name] ~= nil then + core.log("WARNING: Not registering alias, item with same name" .. + " is already defined: " .. name .. " -> " .. convert_to) + else + --core.log("Registering alias: " .. name .. " -> " .. convert_to) + core.registered_aliases[name] = convert_to + register_alias_raw(name, convert_to) + end end function core.on_craft(itemstack, player, old_craft_list, craft_inv) - for _, func in ipairs(core.registered_on_crafts) do - itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack - end - return itemstack + for _, func in ipairs(core.registered_on_crafts) do + itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack + end + return itemstack end function core.craft_predict(itemstack, player, old_craft_list, craft_inv) - for _, func in ipairs(core.registered_craft_predicts) do - itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack - end - return itemstack + for _, func in ipairs(core.registered_craft_predicts) do + itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack + end + return itemstack end -- Alias the forbidden item names to "" so they can't be -- created via itemstrings (e.g. /give) local name for name in pairs(forbidden_item_names) do - core.registered_aliases[name] = "" - register_alias_raw(name, "") + core.registered_aliases[name] = "" + register_alias_raw(name, "") end @@ -260,108 +260,111 @@ end -- core.register_item(":unknown", { - type = "none", - description = "Unknown Item", - inventory_image = "unknown_item.png", - on_place = core.item_place, - on_drop = core.item_drop, - groups = {not_in_creative_inventory=1}, - diggable = true, + type = "none", + walkable = true, + description = "Unknown Item", + tiles = {"trans.png"}, + inventory_image = "unknown_item.png", + on_place = core.item_place, + on_drop = core.item_drop, + groups = {not_in_creative_inventory=1}, + diggable = true, + pointable = false, }) core.register_node(":air", { - description = "Air (you hacker you!)", - inventory_image = "unknown_node.png", - wield_image = "unknown_node.png", - drawtype = "airlike", - paramtype = "light", - sunlight_propagates = true, - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - air_equivalent = true, - drop = "", - groups = {not_in_creative_inventory=1}, + description = "Air (you hacker you!)", + inventory_image = "unknown_node.png", + wield_image = "unknown_node.png", + drawtype = "airlike", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + air_equivalent = true, + drop = "", + groups = {not_in_creative_inventory=1}, }) core.register_node(":ignore", { - description = "Ignore (you hacker you!)", - inventory_image = "unknown_node.png", - wield_image = "unknown_node.png", - drawtype = "airlike", - paramtype = "none", - sunlight_propagates = false, - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, -- A way to remove accidentally placed ignores - air_equivalent = true, - drop = "", - groups = {not_in_creative_inventory=1}, + description = "Ignore (you hacker you!)", + inventory_image = "unknown_node.png", + wield_image = "unknown_node.png", + drawtype = "airlike", + paramtype = "none", + sunlight_propagates = false, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, -- A way to remove accidentally placed ignores + air_equivalent = true, + drop = "", + groups = {not_in_creative_inventory=1}, }) -- The hand (bare definition) core.register_item(":", { - type = "none", - groups = {not_in_creative_inventory=1}, + type = "none", + groups = {not_in_creative_inventory=1}, }) function core.override_item(name, redefinition) - if redefinition.name ~= nil then - error("Attempt to redefine name of "..name.." to "..dump(redefinition.name), 2) - end - if redefinition.type ~= nil then - error("Attempt to redefine type of "..name.." to "..dump(redefinition.type), 2) - end - local item = core.registered_items[name] - if not item then - error("Attempt to override non-existent item "..name, 2) - end - for k, v in pairs(redefinition) do - rawset(item, k, v) - end - register_item_raw(item) + if redefinition.name ~= nil then + error("Attempt to redefine name of "..name.." to "..dump(redefinition.name), 2) + end + if redefinition.type ~= nil then + error("Attempt to redefine type of "..name.." to "..dump(redefinition.type), 2) + end + local item = core.registered_items[name] + if not item then + error("Attempt to override non-existent item "..name, 2) + end + for k, v in pairs(redefinition) do + rawset(item, k, v) + end + register_item_raw(item) end function core.run_callbacks(callbacks, mode, ...) - assert(type(callbacks) == "table") - local cb_len = #callbacks - if cb_len == 0 then - if mode == 2 or mode == 3 then - return true - elseif mode == 4 or mode == 5 then - return false - end - end - local ret = nil - for i = 1, cb_len do - local cb_ret = callbacks[i](...) + assert(type(callbacks) == "table") + local cb_len = #callbacks + if cb_len == 0 then + if mode == 2 or mode == 3 then + return true + elseif mode == 4 or mode == 5 then + return false + end + end + local ret = nil + for i = 1, cb_len do + local cb_ret = callbacks[i](...) - if mode == 0 and i == 1 then - ret = cb_ret - elseif mode == 1 and i == cb_len then - ret = cb_ret - elseif mode == 2 then - if not cb_ret or i == 1 then - ret = cb_ret - end - elseif mode == 3 then - if cb_ret then - return cb_ret - end - ret = cb_ret - elseif mode == 4 then - if (cb_ret and not ret) or i == 1 then - ret = cb_ret - end - elseif mode == 5 and cb_ret then - return cb_ret - end - end - return ret + if mode == 0 and i == 1 then + ret = cb_ret + elseif mode == 1 and i == cb_len then + ret = cb_ret + elseif mode == 2 then + if not cb_ret or i == 1 then + ret = cb_ret + end + elseif mode == 3 then + if cb_ret then + return cb_ret + end + ret = cb_ret + elseif mode == 4 then + if (cb_ret and not ret) or i == 1 then + ret = cb_ret + end + elseif mode == 5 and cb_ret then + return cb_ret + end + end + return ret end -- @@ -369,42 +372,40 @@ end -- local function make_registration() - local t = {} - local registerfunc = function(func) table.insert(t, func) end - return t, registerfunc + local t = {} + local registerfunc = function(func) table.insert(t, func) end + return t, registerfunc end local function make_registration_reverse() - local t = {} - local registerfunc = function(func) table.insert(t, 1, func) end - return t, registerfunc + local t = {} + local registerfunc = function(func) table.insert(t, 1, func) end + return t, registerfunc end local function make_registration_wrap(reg_fn_name, clear_fn_name) - local list = {} + local list = {} - local orig_reg_fn = core[reg_fn_name] - core[reg_fn_name] = function(def) - local retval = orig_reg_fn(def) - if retval ~= nil then - if def.name ~= nil then - list[def.name] = def - else - list[retval] = def - end - end - return retval - end + local orig_reg_fn = core[reg_fn_name] + core[reg_fn_name] = function(def) + local retval = orig_reg_fn(def) + if retval ~= nil then + if def.name ~= nil then + list[def.name] = def + else + list[retval] = def + end + end + return retval + end - local orig_clear_fn = core[clear_fn_name] - core[clear_fn_name] = function() - for k in pairs(list) do - list[k] = nil - end - return orig_clear_fn() - end + local orig_clear_fn = core[clear_fn_name] + core[clear_fn_name] = function() + list = {} + return orig_clear_fn() + end - return list + return list end core.registered_biomes = make_registration_wrap("register_biome", "clear_registered_biomes") @@ -420,6 +421,7 @@ core.registered_on_placenodes, core.register_on_placenode = make_registration() core.registered_on_dignodes, core.register_on_dignode = make_registration() core.registered_on_generateds, core.register_on_generated = make_registration() core.registered_on_newplayers, core.register_on_newplayer = make_registration() +core.registered_on_open_inventories, core.register_on_open_inventory = make_registration() core.registered_on_dieplayers, core.register_on_dieplayer = make_registration() core.registered_on_respawnplayers, core.register_on_respawnplayer = make_registration() core.registered_on_prejoinplayers, core.register_on_prejoinplayer = make_registration() @@ -432,6 +434,38 @@ core.registered_craft_predicts, core.register_craft_predict = make_registration( core.registered_on_protection_violation, core.register_on_protection_violation = make_registration() core.registered_on_item_eats, core.register_on_item_eat = make_registration() +minetest.register_on_joinplayer(function(player) + if minetest.is_singleplayer() then + return + end + local player_name = player:get_player_name() + minetest.chat_send_all("*** " .. player_name .. " joined the game.") +end) + +minetest.register_on_dieplayer(function(player) + local player_name = player:get_player_name() + if minetest.is_singleplayer() then + player_name = "You" + end + + -- Idea from https://github.com/4Evergreen4/death_messages + -- Death by lava + local nodename = minetest.get_node(player:getpos()).name + if nodename == "default:lava_source" or nodename == "default:lava_flowing" then + minetest.chat_send_all(player_name .. " melted into a ball of fire.") + -- Death by drowning + elseif nodename == "default:water_source" or nodename == "default:water_flowing" then + minetest.chat_send_all(player_name .. " ran out of air.") + --Death by fire + elseif nodename == "fire:basic_flame" then + minetest.chat_send_all(player_name .. " burned up.") + --Death by something else + else + minetest.chat_send_all(player_name .. " \vbb0000died.") + end + +end) + -- -- Compatibility for on_mapgen_init() -- diff --git a/builtin/game/stat.lua b/builtin/game/stat.lua new file mode 100644 index 000000000..346a40617 --- /dev/null +++ b/builtin/game/stat.lua @@ -0,0 +1,75 @@ +-- TODO: move this function to builtin/common/misc_helpers.lua +-- +-- Formats numbers according to SI multiplies and +-- appends a correspending prefix symbol (e.g. 1234000 -> 1.234 M) +function string.number_to_si(value, precision) + precision = precision or 3 + local symbol = { "Y", "Z", "E", "P", "T", "G", "M", "k" } + local multiplies = { 10^24, 10^21, 10^18, 10^15, 10^12, 10^9, 10^6, 10^3 } + + local abs_value = math.abs(value) + for k,v in ipairs(multiplies) do + if abs_value >= v then + return string.format("%."..precision.."f "..symbol[k], value / v) + end + end + return math.ceil(value) +end + +-- returns formspec with table of stats +function core.stat_formspec(name) + local stat_table = { + chat = "Messages", + craft = "Crafted", + damage = "Damage", + die = "Deaths", + dig = "Digged", + drop = "Dropped", + join = "Join", + move = "Traveled", + place = "Placed", + punch = "Punches", + use = "Uses", + } + + local formspec + local y = -.1 + + if core.is_singleplayer() then + -- collumns + local x = { .25, 1.8 } + formspec = "size[3.2,4.6]" + .."label["..x[1]..","..y..";Stat]" + .."label["..x[2]..","..y..";Value]" + .."label[-.25,"..(y+0.1)..";"..string.rep("_", 45).."]" + y = y + 0.2 + for key, eng_name in pairs(stat_table) do + -- leading + y = y + 0.4 + formspec = formspec + .."label["..x[1]..","..y..";"..eng_name.."]" + .."label["..x[2]..","..y..";" + ..string.number_to_si(core.stat_get("player|"..key.."|"..name)).."]" + end + else + -- collumns + local x = { .25, 1.8, 3.5 } + formspec = "size[4.9,4.6]" + .."label["..x[1]..","..y..";Stat]" + .."label["..x[2]..","..y..";Player]" + .."label["..x[3]..","..y..";Total]" + .."label[-.25,"..(y+0.1)..";"..string.rep("_", 60).."]" + y = y + 0.2 + for key, eng_name in pairs(stat_table) do + -- leading + y = y + 0.4 + formspec = formspec + .."label["..x[1]..","..y..";"..eng_name.."]" + .."label["..x[2]..","..y..";" + ..string.number_to_si(core.stat_get("player|"..key.."|"..name)).."]" + .."label["..x[3]..","..y..";" + ..string.number_to_si(core.stat_get("total|"..key), 4).."]" + end + end + return formspec +end diff --git a/builtin/game/static_spawn.lua b/builtin/game/static_spawn.lua index 2f21a7337..492ab6ca6 100644 --- a/builtin/game/static_spawn.lua +++ b/builtin/game/static_spawn.lua @@ -1,4 +1,4 @@ --- multicraft: builtin/static_spawn.lua +-- Minetest: builtin/static_spawn.lua local function warn_invalid_static_spawnpoint() if core.setting_get("static_spawnpoint") and diff --git a/builtin/init.lua b/builtin/init.lua index 0b8340316..8f92fc476 100644 --- a/builtin/init.lua +++ b/builtin/init.lua @@ -1,5 +1,5 @@ -- --- This file contains built-in stuff in multicraft implemented in Lua. +-- This file contains built-in stuff in Minetest implemented in Lua. -- -- It is always loaded and executed after registration of the C API, -- before loading and running any mods. @@ -9,7 +9,9 @@ print = core.debug math.randomseed(os.time()) os.setlocale("C", "numeric") -multicraft = core +minetest = core +freeminer = core +magichet = core -- Load other files local scriptdir = core.get_builtin_path()..DIR_DELIM @@ -17,10 +19,15 @@ local gamepath = scriptdir.."game"..DIR_DELIM local commonpath = scriptdir.."common"..DIR_DELIM local asyncpath = scriptdir.."async"..DIR_DELIM +--dofile(scriptdir.."profiler.lua") --TODO: repair me +--[[ too buggy dofile(commonpath.."strict.lua") +]] dofile(commonpath.."serialize.lua") dofile(commonpath.."misc_helpers.lua") +dofile(scriptdir.."key_value_storage.lua") + if INIT == "game" then dofile(gamepath.."init.lua") elseif INIT == "mainmenu" then @@ -28,7 +35,7 @@ elseif INIT == "mainmenu" then if mainmenuscript ~= nil and mainmenuscript ~= "" then dofile(mainmenuscript) else - dofile(core.get_mainmenu_path()..DIR_DELIM.."init.lua") + dofile(core.get_mainmenu_path()..DIR_DELIM.."fm_init.lua") end elseif INIT == "async" then dofile(asyncpath.."init.lua") diff --git a/builtin/key_value_storage.lua b/builtin/key_value_storage.lua new file mode 100644 index 000000000..39c740fe0 --- /dev/null +++ b/builtin/key_value_storage.lua @@ -0,0 +1,26 @@ +-- +-- Key-value storage stuff +-- + +function core.kv_put(key, data) + local json = core.write_json(data) + if not json then + core.log("error", "kv_put: Error in json serialize key=".. key .. " luaized_data=" .. core.serialize(data)) + return + end + return core.kv_put_string(key, json) +end + +function core.kv_get(key) + local data = core.kv_get_string(key) + if data ~= nil then + data = core.parse_json(data) + end + return data +end + +function core.kv_rename(key1, key2) + local data = core.kv_get_string(key1) + core.kv_delete(key1) + core.kv_put_string(key2, data) +end diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index 17054d0f4..3d312dd0c 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -16,278 +16,206 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- -- Global menu data --------------------------------------------------------------------------------- +--------------------------------------------------------------------------------- menudata = {} --------------------------------------------------------------------------------- --- Local cached values --------------------------------------------------------------------------------- -local min_supp_proto = core.get_min_supp_proto() -local max_supp_proto = core.get_max_supp_proto() - -------------------------------------------------------------------------------- -- Menu helper functions -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- local function render_client_count(n) - n = tonumber(n) - if n > 99 then - return '99+' - elseif n >= 0 then - return tostring(n) - else - return '?' - end -end - -local function configure_selected_world_params(idx) - local worldconfig = modmgr.get_worldconfig( - menudata.worldlist:get_list()[idx].path) - - if worldconfig.creative_mode ~= nil then - core.setting_set("creative_mode", worldconfig.creative_mode) - end - if worldconfig.enable_damage ~= nil then - core.setting_set("enable_damage", worldconfig.enable_damage) - end -end - --------------------------------------------------------------------------------- -function image_column(tooltip, flagname) - return "image," .. - "tooltip=" .. core.formspec_escape(tooltip) .. "," .. - "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. - "1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png") -end - --------------------------------------------------------------------------------- -function order_favorite_list(list) - local res = {} - --orders the favorite list after support - for i=1,#list,1 do - local fav = list[i] - if is_server_protocol_compat(tonumber(fav.proto_min), tonumber(fav.proto_max)) then - table.insert(res, fav) - end - end - for i=1,#list,1 do - local fav = list[i] - if not is_server_protocol_compat(tonumber(fav.proto_min), tonumber(fav.proto_max)) then - table.insert(res, fav) - end - end - return res + if tonumber(n) > 99 then + return '99+' + elseif tonumber(n) >= 0 then + return tostring(n) + else + return '?' + end end -------------------------------------------------------------------------------- function render_favorite(spec,render_details) - local text = "" + local text = "" - if spec.name ~= nil then - text = text .. core.formspec_escape(spec.name:trim()) + 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.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 spec.port ~= nil then + text = text .. ":" .. spec.port + end + end + end - if not render_details then - return text - end + local details = "" - local details = "" - local grey_out = not is_server_protocol_compat(tonumber(spec.proto_max), tonumber(spec.proto_min)) + if spec.clients ~= nil and spec.clients_max ~= nil then + local clients_color = '' + local clients_percent = 100 * spec.clients / spec.clients_max - if spec.clients ~= nil and spec.clients_max ~= nil then - local clients_color = '' - local clients_percent = 100 * spec.clients / spec.clients_max + -- Choose a color depending on how many clients are connected + -- (relatively to clients_max) + if spec.clients == 0 then + clients_color = '' -- 0 players: default/white + elseif spec.clients == spec.clients_max then + clients_color = '#dd5b5b' -- full server: red (darker) + elseif clients_percent <= 60 then + clients_color = '#a1e587' -- 0-60%: green + elseif clients_percent <= 90 then + clients_color = '#ffdc97' -- 60-90%: yellow + else + clients_color = '#ffba97' -- 90-100%: orange + end - -- Choose a color depending on how many clients are connected - -- (relatively to clients_max) - if spec.clients == 0 then - clients_color = '' -- 0 players: default/white - elseif spec.clients == spec.clients_max then - clients_color = '#dd5b5b' -- full server: red (darker) - elseif clients_percent <= 60 then - clients_color = '#a1e587' -- 0-60%: green - elseif clients_percent <= 90 then - clients_color = '#ffdc97' -- 60-90%: yellow - else - clients_color = '#ffba97' -- 90-100%: orange - end + details = details .. + clients_color .. ',' .. + render_client_count(spec.clients) .. ',' .. + '/,' .. + render_client_count(spec.clients_max) .. ',' + else + details = details .. ',?,/,?,' + end - if grey_out then - clients_color = '#aaaaaa' - end + if spec.creative then + details = details .. "1," + else + details = details .. "0," + end - details = details .. - clients_color .. ',' .. - render_client_count(spec.clients) .. ',' .. - '/,' .. - render_client_count(spec.clients_max) .. ',' - elseif grey_out then - details = details .. '#aaaaaa,?,/,?,' - else - details = details .. ',?,/,?,' - end + if spec.damage then + details = details .. "1," + else + details = details .. "0," + end - if spec.creative then - details = details .. "1," - else - details = details .. "0," - end + if spec.pvp then + details = details .. "1," + else + details = details .. "0," + end - if spec.damage then - details = details .. "1," - else - details = details .. "0," - end - - if spec.pvp then - details = details .. "1," - else - details = details .. "0," - end - - return details .. (grey_out and '#aaaaaa,' or ',') .. text + details = details .. text + return details end -------------------------------------------------------------------------------- os.tempfolder = function() - if core.setting_get("TMPFolder") then - return core.setting_get("TMPFolder") .. DIR_DELIM .. "MT_" .. math.random(0,10000) - end + 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 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 + 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 retval = "" - local current_worldlist = menudata.worldlist:get_list() + local current_worldlist = menudata.worldlist:get_list() - for i,v in ipairs(current_worldlist) do - if retval ~= "" then - retval = retval .."," - end + 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 + retval = retval .. core.formspec_escape(v.name) .. + " \\[" .. core.formspec_escape(v.gameid) .. "\\]" + end - return retval + 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)) + if fields["key_up"] then + local oldidx = core.get_textlist_index(textlist) - configure_selected_world_params(newidx) - end - return true - end + 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 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)) + if oldidx ~= nil and oldidx < menudata.worldlist:size() then + local newidx = oldidx + 1 + core.setting_set(settingname, + menudata.worldlist:get_raw_index(newidx)) + end - configure_selected_world_params(newidx) - end - - return true - end - - return false + return true + end + + return false end -------------------------------------------------------------------------------- function asyncOnlineFavourites() - menudata.favorites = {} - core.handle_async( - function(param) - return core.get_favorites("online") - end, - nil, - function(result) - if core.setting_getbool("public_serverlist") then - menudata.favorites = order_favorite_list(result) - core.event_handler("Refresh") - end - end - ) + menudata.favorites = {} + core.handle_async( + function(param) + local ret = core.get_favorites("online") + local num = core.get_favorites("local") + local cou = 0 + for k,v in ipairs(core.get_favorites("local")) do + cou = cou+1 + table.insert(ret,cou,v) + end + return ret + 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 textlines = core.splittext(text,textlen) - local retval = "textlist[" .. xpos .. "," .. ypos .. ";" - .. width .. "," .. height .. ";" - .. tl_name .. ";" + 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 + for i=1, #textlines, 1 do + textlines[i] = textlines[i]:gsub("\r","") + retval = retval .. core.formspec_escape(textlines[i]) .. "," + end - retval = retval .. ";0;" + retval = retval .. ";0;" - if transparency then - retval = retval .. "true" - end + if transparency then + retval = retval .. "true" + end - retval = retval .. "]" + retval = retval .. "]" - return retval -end - --------------------------------------------------------------------------------- -function is_server_protocol_compat(proto_min, proto_max) - return not ((min_supp_proto > (proto_max or 24)) or (max_supp_proto < (proto_min or 13))) -end --------------------------------------------------------------------------------- -function is_server_protocol_compat_or_error(proto_min, proto_max) - if not is_server_protocol_compat(proto_min, proto_max) then - gamedata.errormessage = fgettext_ne("Protocol version mismatch, server " .. - ((proto_min ~= proto_max) and "supports protocols between $1 and $2" or "enforces protocol version $1") .. - ", we " .. - ((min_supp_proto ~= max_supp_proto) and "support protocols between version $3 and $4." or "only support protocol version $3"), - proto_min or 13, proto_max or 24, min_supp_proto, max_supp_proto) - return false - end - - return true + return retval end diff --git a/builtin/mainmenu/dlg_add_server.lua b/builtin/mainmenu/dlg_add_server.lua new file mode 100644 index 000000000..aedcd5ff0 --- /dev/null +++ b/builtin/mainmenu/dlg_add_server.lua @@ -0,0 +1,111 @@ +--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 add_server_formspec(dialogdata) + local retval = + "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + + "label[4,3;" .. fgettext("Name") .. "]".. + "field[6.5,3.4;6,0.5;servername;;]" .. + + "label[4,4;" .. fgettext("Address") .. "]".. + "field[6.5,4.4;6,0.5;address;;]" .. + + "label[4,5;" .. fgettext("Port") .. "]".. + "field[6.5,5.4;6,0.5;port;;30000]" .. + + "label[4,6;" .. fgettext("Description") .. "]".. + "field[6.5,6.4;6,0.5;desc;;Added on ".. os.date() .."]" .. + + + "image_button[8,9.54;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;server_add_confirm;".. fgettext("Add") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;server_add_cancel;".. fgettext("Cancel") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + + return retval +end + +local function add_server_buttonhandler(this, fields) + + if fields["server_add_cancel"] then + this:delete() + return true + end + + if fields["server_add_confirm"] + or fields["key_enter"] then + if fields["address"] and fields["port"] then + +---------------------- + local path = core.get_modpath('')..'/../client/'..core.formspec_escape(core.setting_get("serverlist_file")) + local favourites + if path then + local input = io.open(path, "r") + if input then + favourites = input:read("*all") + io.close(input) + --else + --gamedata.errormessage = fgettext("Can't find serverlist_file! ("..path..')') + end + if favourites then + favourites = minetest.parse_json(favourites) + else + favourites = {["list"]={},} + end + + table.insert(favourites.list,{ + ["address"] = fields["te_address"], + ["description"] = "Saved at ".. os.date(), + ["name"] = fields["te_address"], + ["playername"] = fields["te_name"], + ["playerpassword"] = fields["te_pwd"], + ["port"] = fields["te_port"], + } + ) + + favourites = minetest.write_json(favourites) + + --print(path) + local output = io.open(path, "w") + if output then + output:write(favourites or '') + io.close(output) + else + gamedata.errormessage = err..' ('..errcode..')' + end + end +---------------------- + + asyncOnlineFavourites() + this:delete() + end + return true + end + + return false +end + + +function create_add_server_dlg(update_worldlistfilter) + local retval = dialog_create("add_server_dlg", + add_server_formspec, + add_server_buttonhandler, + nil) + return retval +end diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua index e668fc243..f69f54695 100644 --- a/builtin/mainmenu/dlg_config_world.lua +++ b/builtin/mainmenu/dlg_config_world.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify @@ -16,296 +16,296 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- -local function modname_valid(name) - return not name:find("[^a-z0-9_]") -end local function get_formspec(data) - local mod = data.list:get_list()[data.selected_mod] + local mod = data.list:get_list()[data.selected_mod] - local retval = - "size[11,6.5,false]" .. - "label[0.5,-0.25;" .. fgettext("World:") .. "]" .. - "label[1.75,-0.25;" .. data.worldspec.name .. "]" + local retval = + "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. - 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 + "label[1, 2.5;" .. fgettext("World:") .. "]" .. + "label[2.75,2.5;" .. data.worldspec.name .. "]" - 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 data.hide_gamemods then + retval = retval .. "checkbox[1,7.55;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]" + else + retval = retval .. "checkbox[1,7.55;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]" + end - if mod == nil then - mod = {name=""} - end + if data.hide_modpackcontents then + retval = retval .. "checkbox[4,7.55;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]" + else + retval = retval .. "checkbox[4,7.55;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]" + 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]" .. - "image_button[9.25,6.35;2,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_config_world_save;" .. fgettext("Save") .. "]" .. - "image_button[7.4,6.35;2,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_config_world_cancel;" .. fgettext("Cancel") .. "]" + if mod == nil then + mod = {name=""} + end - if mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then - if mod.is_modpack then - local rawlist = data.list:get_raw_list() + retval = retval .. + "label[1,3;" .. fgettext("Mod:") .. "]" .. + "label[2.75,3;" .. mod.name .. "]" .. + "label[8,3;" .. fgettext("Depends:") .. "]" .. + "textlist[8,3.5;7,4.0;world_config_depends;" .. + modmgr.get_dependencies(mod.path) .. ";0]" .. + "image_button[8,9.55;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_config_world_save;" .. fgettext("Save") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_config_world_cancel;".. fgettext("Cancel") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - 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 mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then + if mod.is_modpack then + local rawlist = data.list:get_raw_list() - if all_enabled == false then - retval = retval .. "image_button[5.5,-0.125;2,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mp_enable;" .. fgettext("Enable MP") .. "]" - else - retval = retval .. "image_button[5.5,-0.125;2,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;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 + 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 - retval = retval .. - "image_button[8.5,-0.125;2.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_all_mods;" .. fgettext("Enable all") .. "]" .. - "textlist[5.5,0.5;5.5,5.75;world_config_modlist;" + if all_enabled == false then + retval = retval .. "image_button[8,7.55;3.5,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mp_enable;" .. fgettext("Enable MP") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + else + retval = retval .. "image_button[8,7.85;3.5,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mp_disable;" .. fgettext("Disable MP") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + end + else + if mod.enabled then + retval = retval .. "checkbox[8.25,7.55;cb_mod_enable;" .. fgettext("enabled") .. ";true]" + else + retval = retval .. "checkbox[8.25,7.55;cb_mod_enable;" .. fgettext("enabled") .. ";false]" + end + end + end - retval = retval .. modmgr.render_modlist(data.list) - retval = retval .. ";" .. data.selected_mod .."]" + retval = retval .. + "image_button[11.75,7.55;3.5,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_all_mods;" .. fgettext("Enable all") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "textlist[1,3.5;6,4.0;world_config_modlist;" + --"textlist[5.5,0.5;5.5,5.75;world_config_modlist;" - return retval + 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] + 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 + 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 - core.setting_set("world_config_selected_mod", event.index) + if fields["world_config_modlist"] ~= nil then + local event = core.explode_textlist_event(fields["world_config_modlist"]) + this.data.selected_mod = event.index + core.setting_set("world_config_selected_mod", event.index) - if event.type == "DCL" then - enable_mod(this) - end + if event.type == "DCL" then + enable_mod(this) + end - return true - end + return true + end - if fields["key_enter"] ~= nil then - enable_mod(this) - 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["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["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 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 current == nil then + current = {} + end - if fields["cb_hide_gamemods"] ~= nil then - if core.is_yes(fields["cb_hide_gamemods"]) then - current.hide_game = true - this.data.hide_gamemods = true - core.setting_set("world_config_hide_gamemods", "true") - else - current.hide_game = false - this.data.hide_gamemods = false - core.setting_set("world_config_hide_gamemods", "false") - end - end + if fields["cb_hide_gamemods"] ~= nil then + if core.is_yes(fields["cb_hide_gamemods"]) then + current.hide_game = true + this.data.hide_gamemods = true + core.setting_set("world_config_hide_gamemods", "true") + else + current.hide_game = false + this.data.hide_gamemods = false + core.setting_set("world_config_hide_gamemods", "false") + end + end - if fields["cb_hide_mpcontent"] ~= nil then - if core.is_yes(fields["cb_hide_mpcontent"]) then - current.hide_modpackcontents = true - this.data.hide_modpackcontents = true - core.setting_set("world_config_hide_modpackcontents", "true") - else - current.hide_modpackcontents = false - this.data.hide_modpackcontents = false - core.setting_set("world_config_hide_modpackcontents", "false") - end - end + if fields["cb_hide_mpcontent"] ~= nil then + if core.is_yes(fields["cb_hide_mpcontent"]) then + current.hide_modpackcontents = true + this.data.hide_modpackcontents = true + core.setting_set("world_config_hide_modpackcontents", "true") + else + current.hide_modpackcontents = false + this.data.hide_modpackcontents = false + core.setting_set("world_config_hide_modpackcontents", "false") + end + end - this.data.list:set_filtercriteria(current) - return true - end + this.data.list:set_filtercriteria(current) + return true + end - if fields["btn_config_world_save"] then + if fields["btn_config_world_save"] then - local filename = this.data.worldspec.path .. - DIR_DELIM .. "world.mt" + local filename = this.data.worldspec.path .. + DIR_DELIM .. "world.mt" - local worldfile = Settings(filename) - local mods = worldfile:to_table() + local worldfile = Settings(filename) + local mods = worldfile:to_table() - local rawlist = this.data.list:get_raw_list() + 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 modname_valid(mod.name) then - worldfile:set("load_mod_"..mod.name, tostring(mod.enabled)) - else - if mod.enabled then - gamedata.errormessage = fgettext_ne("Failed to enable mod \"$1\" as it contains disallowed characters. Only chararacters [a-z0-9_] are allowed.", mod.name) - end - end - mods["load_mod_"..mod.name] = nil - end - end + 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 + -- 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 + if not worldfile:write() then + core.log("error", "Failed to write world config file") + end - this:delete() - return true - end + this:delete() + return true + end - if fields["btn_config_world_cancel"] then - 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() + 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 + 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 + return false end function create_configure_world_dlg(worldidx) - local dlg = dialog_create("sp_config_world", - get_formspec, - handle_buttons, - nil) + local dlg = dialog_create("sp_config_world", + get_formspec, + handle_buttons, + nil) - dlg.data.hide_gamemods = core.setting_getbool("world_config_hide_gamemods") - dlg.data.hide_modpackcontents = core.setting_getbool("world_config_hide_modpackcontents") - dlg.data.selected_mod = tonumber(core.setting_get("world_config_selected_mod")) - if dlg.data.selected_mod == nil then - dlg.data.selected_mod = 0 - end + dlg.data.hide_gamemods = core.setting_getbool("world_config_hide_gamemods") + dlg.data.hide_modpackcontents = core.setting_getbool("world_config_hide_modpackcontents") + dlg.data.selected_mod = tonumber(core.setting_get("world_config_selected_mod")) + if dlg.data.selected_mod == nil then + dlg.data.selected_mod = 0 + end - dlg.data.worldspec = core.get_worlds()[worldidx] - if dlg.data.worldspec == nil then dlg:delete() return nil end + 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) + 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 + if dlg.data.worldconfig == nil or dlg.data.worldconfig.id == nil or + dlg.data.worldconfig.id == "" then - dlg:delete() - return nil - end + 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 + 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 } - ) + 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 } + ) - if dlg.data.selected_mod > dlg.data.list:size() then - dlg.data.selected_mod = 0 - end + if dlg.data.selected_mod > dlg.data.list:size() then + dlg.data.selected_mod = 0 + end - 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") + 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 + return dlg end diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 086743f03..ef2fc7288 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -16,128 +16,137 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. local function create_world_formspec(dialogdata) - local mapgens = core.get_mapgen_names() + local mapgens = core.get_mapgen_names() - local current_seed = core.setting_get("fixed_map_seed") or "" - local current_mg = core.setting_get("mg_name") + 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 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 gameid = core.setting_get("menu_last_game") - local game, gameidx = nil , 0 - if gameid ~= nil then - game, gameidx = gamemgr.find_by_gameid(gameid) + local game, gameidx = nil , 0 + if gameid ~= nil then + game, gameidx = gamemgr.find_by_gameid(gameid) - if gameidx == nil then - gameidx = 0 - end - end + if gameidx == nil then + gameidx = 1 + end + end - current_seed = core.formspec_escape(current_seed) - local retval = - "size[12,6,false]" .. - "label[2,0;" .. fgettext("World name") .. "]".. - "field[4.5,0.4;6,0.5;te_world_name;;]" .. + current_seed = core.formspec_escape(current_seed) + local retval = + "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. - "label[2,1;" .. fgettext("Seed") .. "]".. - "field[4.5,1.4;6,0.5;te_seed;;".. current_seed .. "]" .. + "label[4,3;" .. fgettext("World name") .. "]".. + "field[6.5,3.4;6,0.5;te_world_name;;]" .. - "label[2,2;" .. fgettext("Mapgen") .. "]".. - "dropdown[4.2,2;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" .. + "label[4,4;" .. fgettext("Seed") .. "]".. + "field[6.5,4.4;6,0.5;te_seed;;".. current_seed .. "]" .. - "label[2,3;" .. fgettext("Game") .. "]".. - "textlist[4.2,3;5.8,2.3;games;" .. gamemgr.gamelist() .. - ";" .. gameidx .. ";true]" .. + "label[4,5;" .. fgettext("Mapgen") .. "]".. + "dropdown[6.2,5;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" .. - "image_button[5,5.5;2.6,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create_confirm;" .. fgettext("Create") .. "]" .. - "image_button[7.5,5.5;2.8,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create_cancel;" .. fgettext("Cancel") .. "]" + "label[4,6;" .. fgettext("Game") .. "]".. + "dropdown[6.2,6;6.3;games;" .. gamemgr.gamelist() .. + ";" .. gameidx .. "]" .. - if #gamemgr.games == 0 then - retval = retval .. "box[2,4;8,1;#ff8800]label[2.25,4;" .. - fgettext("You have no subgames installed.") .. "]label[2.25,4.4;" .. - fgettext("Download one from multicraft.net") .. "]" - elseif #gamemgr.games == 1 and gamemgr.games[1].id == "minimal" then - retval = retval .. "box[1.75,4;8.7,1;#ff8800]label[2,4;" .. - fgettext("Warning: The minimal development test is meant for developers.") .. "]label[2,4.4;" .. - fgettext("Download a subgame, such as multicraft_game, from multicraft.net") .. "]" - end - return retval + "image_button[8,9.55;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create_confirm;".. fgettext("Create") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create_cancel;".. fgettext("Cancel") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + + if #gamemgr.games == 0 then + retval = retval .. "box[4,7;8,1;#ff8800]label[4.25,7;" .. + fgettext("You have no subgames installed.") .. "]label[4.25,7.4;" .. + fgettext("Download one from minetest.net") .. "]" + elseif #gamemgr.games == 1 and gamemgr.games[1].id == "minimal" then + retval = retval .. "box[3.50,7;9,1;#ff8800]label[3.75,7;" .. + fgettext("Warning: The minimal development test is meant for developers.") .. "]label[3.75,7.4;" .. + fgettext("Download a subgame, such as minetest_game, from minetest.net") .. "]" + end + + return retval end local function create_world_buttonhandler(this, fields) - if fields["world_create_confirm"] or - fields["key_enter"] then + if fields["world_create_cancel"] then + this:delete() + return true + end - local worldname = fields["te_world_name"] - local gameindex = core.get_textlist_index("games") + if fields["world_create_confirm"] or + fields["key_enter"] then - if gameindex ~= nil and - worldname ~= "" then + local worldname = fields["te_world_name"] + local gameindex + for i,item in ipairs(gamemgr.games) do + if item.name == fields["games"] then + gameindex = i + end + end + if gameindex ~= nil and + worldname ~= "" then - local message = nil + local message = nil - core.setting_set("fixed_map_seed", fields["te_seed"]) + 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 - 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 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["games"] then + return true + end - if fields["world_create_cancel"] then - this:delete() - return true - end - - return false + 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 + local retval = dialog_create("sp_create_world", + create_world_formspec, + create_world_buttonhandler, + nil) + retval.update_worldlist_filter = update_worldlistfilter - return retval + return retval end diff --git a/builtin/mainmenu/dlg_delete_mod.lua b/builtin/mainmenu/dlg_delete_mod.lua index c0a491abd..81bcf2b96 100644 --- a/builtin/mainmenu/dlg_delete_mod.lua +++ b/builtin/mainmenu/dlg_delete_mod.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -19,50 +19,53 @@ local function delete_mod_formspec(dialogdata) - dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected] + dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected] - local retval = - "size[12.4,5,false]" .. - "field[1.75,1;10,3;;" .. fgettext("Are you sure you want to delete \"$1\"?", dialogdata.mod.name) .. ";]".. - "image_button[4,4.2;1,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_delete_mod_confirm;" .. fgettext("Yes") .. "]" .. - "image_button[6.5,4.2;3,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_delete_mod_cancel;" .. fgettext("No of course not!") .. "]" - - return retval + local retval = + "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + "label[6.5,4.5;" .. + fgettext("Are you sure you want to delete \"$1\"?", dialogdata.mod.name) .. ";]".. + "image_button[4,5.7;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_delete_mod_confirm;" .. fgettext("Yes").. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[8,5.7;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_delete_mod_cancel;" .. fgettext("No") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + return retval end -------------------------------------------------------------------------------- local function delete_mod_buttonhandler(this, fields) - if fields["dlg_delete_mod_confirm"] ~= nil then + 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 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 + if fields["dlg_delete_mod_cancel"] then + this:delete() + return true + end - return false + 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 + 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 index 55627d6a0..8fb21ae02 100644 --- a/builtin/mainmenu/dlg_delete_world.lua +++ b/builtin/mainmenu/dlg_delete_world.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -18,47 +18,50 @@ local function delete_world_formspec(dialogdata) - local retval = - "size[12,6,false]" .. - "label[2,2;" .. - fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]".. - "image_button[3.5,4.2;2.6,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete_confirm;" .. fgettext("Yes").. "]" .. - "image_button[6,4.2;2.8,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete_cancel;" .. fgettext("No") .. "]" - return retval + local retval = + "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + "label[6.5,4.5;" .. + fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]".. + "image_button[4,5.7;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete_confirm;" .. fgettext("Yes").. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[8,5.7;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete_cancel;" .. fgettext("No") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + return retval end local function delete_world_buttonhandler(this, fields) - if fields["world_delete_confirm"] then + 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 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 + if fields["world_delete_cancel"] then + this:delete() + return true + end - return false + 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") + 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("delete_world", - delete_world_formspec, - delete_world_buttonhandler, - nil) - retval.data.delete_name = name_to_del - retval.data.delete_index = index_to_del + local retval = dialog_create("delete_world", + delete_world_formspec, + delete_world_buttonhandler, + nil) + retval.data.delete_name = name_to_del + retval.data.delete_index = index_to_del - return retval + return retval end diff --git a/builtin/mainmenu/dlg_rename_modpack.lua b/builtin/mainmenu/dlg_rename_modpack.lua index 7d47c4421..19eb2be60 100644 --- a/builtin/mainmenu/dlg_rename_modpack.lua +++ b/builtin/mainmenu/dlg_rename_modpack.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -19,51 +19,51 @@ local function rename_modpack_formspec(dialogdata) - dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected] + dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected] - local retval = - "size[12.4,5,false]" .. - "label[1.75,1;".. fgettext("Rename Modpack:") .. "]".. - "field[4.5,1.4;6,0.5;te_modpack_name;;" .. - dialogdata.mod.name .. - "]" .. - "image_button[5,4.2;2.6,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_rename_modpack_confirm;".. - fgettext("Accept") .. "]" .. - "image_button[7.5,4.2;2.8,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_rename_modpack_cancel;".. - fgettext("Cancel") .. "]" + 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 .. + "]" .. + "image_button[5,4.2;2.6,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_rename_modpack_confirm;".. + fgettext("Accept") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[7.5,4.2;2.8,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_rename_modpack_cancel;".. + fgettext("Cancel") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - return retval + 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"])) + 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 + this:delete() + return true + end - if fields["dlg_rename_modpack_cancel"] then - this:delete() - return true - end + if fields["dlg_rename_modpack_cancel"] then + this:delete() + return true + end - return false + 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 + 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/fm_gamemgr.lua b/builtin/mainmenu/fm_gamemgr.lua new file mode 100644 index 000000000..433290654 --- /dev/null +++ b/builtin/mainmenu/fm_gamemgr.lua @@ -0,0 +1,321 @@ +--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. + +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 = core.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 = core.get_gamepath() + + if gamepath ~= nil and + gamepath ~= "" then + local gamefolder = cleanup_path(fields["te_game_name"]) + + --TODO check for already existing first + core.create_dir(gamepath .. DIR_DELIM .. gamefolder) + core.create_dir(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "mods") + core.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 = core.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 = core.setting_get("main_menu_tab") + } + end + + if fields["btn_remove_mod_from_game"] ~= nil then + gamemgr.delete_mod(current_game,core.get_textlist_index("mods_current")) + end + + if fields["btn_add_mod_to_game"] ~= nil then + local modindex = core.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 core.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 + core.delete_dir(game_mods[modindex].path) + end + end + end +end + +-------------------------------------------------------------------------------- +function gamemgr.find_by_gameid(gameid) + for i=1,#gamemgr.games,1 do + if gamemgr.games[i].id == gameid then + return gamemgr.games[i], i + end + end + return nil, nil +end + +-------------------------------------------------------------------------------- +function gamemgr.get_game_mods(gamespec, retval) + if gamespec ~= nil and + gamespec.gamemods_path ~= nil and + gamespec.gamemods_path ~= "" then + get_mods(gamespec.gamemods_path, retval) + end +end + +-------------------------------------------------------------------------------- +function gamemgr.get_game_modlist(gamespec) + local retval = "" + local game_mods = {} + gamemgr.get_game_mods(gamespec, game_mods) + for i=1,#game_mods,1 do + if retval ~= "" then + 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 = + "label[6.5,-0.25;" .. fgettext("Games") .. ":]" .. + "textlist[6.5,0.25;8,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[6.5,5.5;2,2;" .. + core.formspec_escape(current_game.menuicon_path) .. "]" + end + + retval = retval .. + "field[9,5.5;6,2;;" .. current_game.name .. ";]".. + "label[6.5,7.2;" .. fgettext("Mods:") .."]" .. + "button[6.5,11.4;3.2,0.2;btn_game_mgr_edit_game;" .. fgettext("edit game") .. "]" .. + "textlist[6.5,7.7;8,3.3;game_mgr_modlist;" + .. gamemgr.get_game_modlist(current_game) ..";0]" .. + "button[6.5,4.9;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;" .. + core.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) + if index > 0 and index <= #gamemgr.games then + return gamemgr.games[index] + end + + return nil +end + +-------------------------------------------------------------------------------- +function gamemgr.update_gamelist() + gamemgr.games = core.get_games() +end + +-------------------------------------------------------------------------------- +function gamemgr.gamelist() + local retval = "" + if #gamemgr.games > 0 then + retval = retval .. gamemgr.games[1].name + + for i=2,#gamemgr.games,1 do + retval = retval .. "," .. gamemgr.games[i].name + end + end + return retval +end diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/fm_init.lua similarity index 53% rename from builtin/mainmenu/init.lua rename to builtin/mainmenu/fm_init.lua index 81c1d90ea..b985f6d95 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/fm_init.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -25,7 +25,7 @@ mt_color_dark_green = "#003300" 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 + DIR_DELIM .. "pack" .. DIR_DELIM dofile(basepath .. DIR_DELIM .. "common" .. DIR_DELIM .. "async_event.lua") dofile(basepath .. DIR_DELIM .. "common" .. DIR_DELIM .. "filterlist.lua") @@ -41,57 +41,55 @@ dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") dofile(menupath .. DIR_DELIM .. "tab_credits.lua") dofile(menupath .. DIR_DELIM .. "tab_mods.lua") dofile(menupath .. DIR_DELIM .. "tab_settings.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_multiplayer.lua") - dofile(menupath .. DIR_DELIM .. "tab_server.lua") - dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua") - dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua") - dofile(menupath .. DIR_DELIM .. "textures.lua") +dofile(menupath .. DIR_DELIM .. "tab_help.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 .. "dlg_add_server.lua") + dofile(menupath .. DIR_DELIM .. "tab_multiplayer.lua") + dofile(menupath .. DIR_DELIM .. "tab_server.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 - return true + if event == "MenuQuit" then + core.close() + end + + return true end -------------------------------------------------------------------------------- local function get_formspec2(tabview, name, tabdata) - local retval = 'size[12,5.2,false]' - retval = retval .. "bgcolor[#00000000;true]" - retval = retval .. "image_button[2.5,3.4;7,1;"..multicraft.formspec_escape(mm_texture.basetexturedir) .. "menu_button.png;btn_show_multiplayer;" .. fgettext("Multiplayer") .. ";true;true;" .. multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - retval = retval .. "image_button[2.5,4.8;7,1;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_options;".. fgettext("Options") .. ";true;true;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - --retval = retval .. "image_button[8.5,4.8;1,1;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_help;?;true;true;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - retval = retval .. "image_button[2.5,6.2;7,1;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_exit;".. fgettext("Exit") .. ";true;true;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - retval = retval .. "image_button[2.5,2.0;7,1;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_singleplayer;".. fgettext("Singleplayer") .. ";true;true;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + local retval = "" + retval = retval .. "bgcolor[#00000000;false]" + retval = retval .. "image_button[2.5,3.4;7,1;"..minetest.formspec_escape(mm_texture.basetexturedir) .. "menu_button.png;btn_show_multiplayer;" .. fgettext("Multiplayer") .. ";true;true;" .. minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + retval = retval .. "image_button[2.5,4.8;6,1;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_options;".. fgettext("Options") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + retval = retval .. "image_button[8.5,4.8;1,1;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_help;?;true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + retval = retval .. "image_button[2.5,6.2;7,1;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_exit;".. fgettext("Exit") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + retval = retval .. "image_button[2.5,2.0;7,1;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_singleplayer;".. fgettext("Singleplayer") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" local si = core.get_screen_info() local ydiv = si.window_height/5.2 local xdiv = si.window_width/12.5 local ratio = xdiv/ydiv - print('Width: '..si.window_width) - print('Height: '..si.window_height) - print(xdiv..' x '..ydiv..' = '..ratio) - --math.randomseed(os.time()) - print('Chosen font size: '.. math.floor(si.window_width/53.33)+0.5) - core.setting_set('font_size', tostring(math.floor(si.window_width/53.33)+0.5)) - --local rnd = 'image['.. 12*ratio ..','.. 1 .. ';6,0.5;'..multicraft.formspec_escape(mm_texture.basetexturedir)..'ad_label'..tostring(math.random(1,14))..'.png]' - print('----') - print(retval) - print('----') - return retval --.. rnd + --print(xdiv..' x '..ydiv..' = '..ratio) + + math.randomseed(os.time()) + local rnd = 'image['.. 12*ratio ..','.. 1 .. ';6,0.5;'..minetest.formspec_escape(mm_texture.basetexturedir)..'ad_label'..tostring(math.random(1,14))..'.png]' + + return retval .. rnd end -------------------------------------------------------------------------------- local function main_button_handler2(tabview, fields, name, tabdata) local index = '' - if fields["btn_show_singleplayer"] then index = "singleplayer" end + if fields["btn_show_singleplayer"] then index = "server" end if fields["btn_show_multiplayer"] then index = "multiplayer" end if fields["btn_show_options"] then index = "settings" end if fields["btn_show_help"] then index = "help" end @@ -99,19 +97,17 @@ local function main_button_handler2(tabview, fields, name, tabdata) if index == '' then return end for name,def in pairs(tabview.tablist) do - local fs - if index == 'singleplayer' then - fs = create_tab_single(true) - elseif index == 'multiplayer' then - fs = create_tab_multiplayer() - elseif index == 'settings' then - fs = create_tab_settings(true) - end - if fs then - fs:set_parent(tabview.parent or tabview) - tabview:hide() - fs:show() - return true + if index == def.name then + local get_fs = function() + local retval = def.get_formspec(tabview, name, tabdata) + retval = 'size[12,5.2]'..retval + return retval + end + local dlg = dialog_create(def.name, get_fs, def.button_handler, def.on_change) + dlg:set_parent(tabview) + tabview:hide() + dlg:show() + return dlg end end return false @@ -130,8 +126,8 @@ local function on_activate2(type,old_tab,new_tab) mm_texture.clear("header") mm_texture.clear("footer") core.set_clouds(false) - core.set_background("background",multicraft.formspec_escape(mm_texture.basetexturedir)..'background.png') - core.set_background("header",multicraft.formspec_escape(mm_texture.basetexturedir)..'header.png') + core.set_background("background",minetest.formspec_escape(mm_texture.basetexturedir)..'background.png') + core.set_background("header",minetest.formspec_escape(mm_texture.basetexturedir)..'header.png') end @@ -174,32 +170,37 @@ local function init_globals() mm_texture.init() - -- Create main tabview - local tv_main = tabview_create("maintab",{x=12,y=5.2},{x=-1,y=0}) - tv_main:set_autosave_tab(false) - tv_main:add(tab_main) - 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_fixed_size(false) - ui.set_default("main") - tv_main:show() + -- Create main tabview + local tv_main = tabview_create("maintab",{x=12,y=5.2},{x=0,y=0}) - -- Create modstore ui - if PLATFORM == "Android" then - modstore.init({x=12, y=6}, 3, 2) - else - modstore.init({x=12, y=8}, 4, 3) - end + tv_main:set_autosave_tab(false) + --tv_main:add(tab_simple_main) + tv_main:add(tab_main) + 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_help) + tv_main:add(tab_credits) - ui.update() + tv_main:set_global_event_handler(main_event_handler) + tv_main:set_fixed_size(false) + ui.set_default("main") - core.sound_play("main_menu", true) + tv_main:show() + + -- Create modstore ui + if PLATFORM == "Android" then + modstore.init({x=12, y=6}, 3, 2) + else + modstore.init({x=12, y=8}, 4, 3) + end + + ui.update() + + core.sound_play("main_menu", true) end diff --git a/builtin/mainmenu/fm_init_orig.lua b/builtin/mainmenu/fm_init_orig.lua new file mode 100644 index 000000000..bd5deb4eb --- /dev/null +++ b/builtin/mainmenu/fm_init_orig.lua @@ -0,0 +1,1361 @@ +local menupath = core.get_mainmenu_path()..DIR_DELIM +local commonpath = core.get_builtin_path()..DIR_DELIM.."common"..DIR_DELIM + +dofile(commonpath.."filterlist.lua") +dofile(commonpath.."async_event.lua") + +dofile(menupath.."fm_modmgr.lua") +dofile(menupath.."fm_gamemgr.lua") + +dofile(menupath.."modstore.lua") +dofile(menupath.."menubar.lua") + +mt_color_grey = "#AAAAAA" +mt_color_blue = "#0000DD" +mt_color_green = "#00DD00" +mt_color_dark_green = "#003300" + +menu = {} +local tabbuilder = {} +local worldlist = nil + +-------------------------------------------------------------------------------- +-- Common/Global menu functions +-------------------------------------------------------------------------------- +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 + +-------------------------------------------------------------------------------- +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 + +-------------------------------------------------------------------------------- +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, + filterlist.get_raw_index(worldlist,newidx)) + end + end + + if fields["key_down"] then + local oldidx = core.get_textlist_index(textlist) + + if oldidx ~= nil and oldidx < filterlist.size(worldlist) then + local newidx = oldidx + 1 + core.setting_set(settingname, + filterlist.get_raw_index(worldlist,newidx)) + end + end +end + +-------------------------------------------------------------------------------- +function menu.asyncOnlineFavourites() + menu.favorites = {} + core.handle_async( + function(param) + return core.get_favorites("online") + end, + nil, + function(result) + menu.favorites = result + core.event_handler("Refresh") + end + ) +end + +-------------------------------------------------------------------------------- +function menu.render_favorite(spec,render_details) + local e = core.formspec_escape + local text = "" + + if spec.name and spec.name ~= "" then + text = text .. spec.name:trim() + else + if spec.address ~= "" then + text = text .. spec.address:trim() + + if spec.port ~= "" then + text = text .. ":" .. spec.port + end + end + end + +--[[ + if not render_details then + return "?,/,?,0,0,0,0," .. e(text) + end +]] + + local row = "" + if spec.clients ~= nil and spec.clients_max ~= nil then + row = row .. e(spec.clients) .. ",/," .. e(spec.clients_max) .. "," + else + row = row .. "?,/,?," + end + + -- 'X and 1 or 0' will return 1 if X is true and 0 if it's false or nil + row = row .. + (spec.password and 1 or 0) .. "," .. + (spec.creative and 1 or 0) .. "," .. + (spec.damage and 1 or 0) .. "," .. + (spec.pvp and 1 or 0) .. "," + + row = row .. e(text) + + return row +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 .. core.formspec_escape(v.name) .. + " \\[" .. core.formspec_escape(v.gameid) .. "\\]" + end + + return retval +end + +-------------------------------------------------------------------------------- +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_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 + +-------------------------------------------------------------------------------- +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 + + + +-------------------------------------------------------------------------------- +-- Global tab functions +-------------------------------------------------------------------------------- +function tabbuilder.gettab() + local tsize = tabbuilder.tabsizes[tabbuilder.current_tab] or {width=12, height=5.2} + local retval = "" + + 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.tab_header() + + if tabbuilder.last_tab_index == nil then + tabbuilder.last_tab_index = 1 + end + + local formspec = "image[-0.35," .. 1.8 + tabbuilder.last_tab_index .. ";" .. core.formspec_escape(menu.defaulttexturedir .. "selected.png") .. "]" + + for i = 1, #tabbuilder.current_buttons do + formspec = formspec .. "label[0.35," .. 2 + i .. ";" .. tabbuilder.current_buttons[i].caption .. "]" + formspec = formspec .. "image_button[-0.4," .. 1.85 + i .. ";6.7,1;" .. core.formspec_escape(menu.defaulttexturedir .. "blank.png") .. ";maintab_" .. i .. ";;true;false]" + end + return formspec +end + +-------------------------------------------------------------------------------- +function tabbuilder.handle_tab_buttons(fields) + local index = nil + local match = "maintab_" + for idx, _ in pairs(fields) do + if idx:sub(1, #match) == match then + index = tonumber(idx:sub(#match + 1, #match + 1)) + break + end + end + + if index then + tabbuilder.last_tab_index = index + tabbuilder.current_tab = tabbuilder.current_buttons[index].name + + core.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 + +-------------------------------------------------------------------------------- +-- Dialogs +-------------------------------------------------------------------------------- +function tabbuilder.dialog_create_world() + local mapgens = {"v5", "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 retval = + "label[6.5,0;" .. fgettext("World name") .. "]".. + "field[9,0.4;6,0.5;te_world_name;;]" .. + + "label[6.5,1;" .. fgettext("Seed") .. "]".. + "field[9,1.4;6,0.5;te_seed;;".. current_seed .. "]" .. + + "label[6.5,2;" .. fgettext("Mapgen") .. "]".. + "dropdown[8.7,2;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" .. + + "label[6.5,3;" .. fgettext("Game") .. "]".. + "textlist[8.7,3;5.8,2.3;games;" .. gamemgr.gamelist() .. + ";" .. menu.last_game .. ";true]" .. + + "button[9.5,5.5;2.6,0.5;world_create_confirm;" .. fgettext("Create") .. "]" .. + "button[12,5.5;2.8,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" + + 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 = core.get_textlist_index("games") + + if gameindex ~= nil and + worldname ~= "" then + + local message = nil + + if not filterlist.uid_exists_raw(worldlist,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 + menu.last_game = gameindex + core.setting_set("main_menu_last_game_idx",gameindex) + + filterlist.refresh(worldlist) + core.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 = core.setting_get("main_menu_tab") +end + +-------------------------------------------------------------------------------- +function tabbuilder.dialog_delete_world() + return "label[6.5,2;" .. + fgettext("Delete World \"$1\"?", filterlist.get_raw_list(worldlist)[menu.world_to_del].name) .. "]".. + "button[8,4.2;2.6,0.5;world_delete_confirm;" .. fgettext("Yes").. "]" .. + "button[10.5,4.2;2.8,0.5;world_delete_cancel;" .. fgettext("No") .. "]" +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 + core.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 = core.setting_get("main_menu_tab") +end + + +-------------------------------------------------------------------------------- +-- Singleplayer tab +-------------------------------------------------------------------------------- +function tabbuilder.tab_singleplayer() + local gameidx = '' + local formspec = '' + local index = filterlist.get_current_index(worldlist, + tonumber(core.setting_get("mainmenu_last_selected_world")) + ) + if menu.lastgame() then + gameidx = menu.lastgame().id + end + formspec = "label[0,2;Game: " .. core.formspec_escape(gameidx) .. "]" .. + "button[7.1,8;3,0.5;world_delete;".. fgettext("Delete") .. "]" .. + "label[7.1,0;".. fgettext("Select World:") .. "]".. + "checkbox[7.1,7.1;cb_creative_mode;".. fgettext("Creative Mode") .. ";" .. + dump(core.setting_getbool("creative_mode")) .. "]".. + "checkbox[10.1,7.1;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. + dump(core.setting_getbool("enable_damage")) .. "]".. + "textlist[7.1,0.5;8.8,6.5;sp_worlds;" .. + menu.render_world_list() .. + ";" .. index .. "]" .. + menubar.formspec + if #gamemgr.games > 0 then + formspec = formspec .. "button[12.85,8.95;3.25,0.5;play;".. fgettext("Play") .. "]" .. + "button[10.1,8;3,0.5;world_create;".. fgettext("New") .. "]" .. + "button[13.1,8;3,0.5;world_configure;".. fgettext("Configure") .. "]" + end + return formspec +end + +-------------------------------------------------------------------------------- +function tabbuilder.handle_singleplayer_buttons(fields) + + 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", + filterlist.get_raw_index(worldlist,core.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 + 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["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 = filterlist.get_raw_index(worldlist,selected) + gamedata.singleplayer = true + + menu.update_last_game(gamedata.selected_world) + + core.start() + end + end + + -- is there any more hacky way to do that? + local world_created = fields["world_create_confirm"] ~= nil or fields["world_create_cancel"] ~= nil or fields["key_enter"] ~= nil + + if (fields["world_create"] ~= nil or fields["dd_mapgen"] ~= nil) and not world_created then + tabbuilder.current_tab = "dialog_create_world" + tabbuilder.is_dialog = true + tabbuilder.show_buttons = true + end + + if fields["world_delete"] ~= nil then + local selected = core.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 = core.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 + + + +-------------------------------------------------------------------------------- +-- Multiplayer tab +-------------------------------------------------------------------------------- +local selected_server = {} + +function tabbuilder.tab_multiplayer() + local e = core.formspec_escape + local retval = + "field[7.35,9;6.75,0.5;te_address;" .. fgettext("Address") .. ";" ..core.setting_get("address") .."]" .. + "field[14.05,9;2.3,0.5;te_port;" .. fgettext("Port") .. ";" ..core.setting_get("remote_port") .."]" .. + "checkbox[7.1,-0.43;cb_public_serverlist;".. fgettext("Public Serverlist") .. ";" .. + dump(core.setting_getbool("public_serverlist")) .. "]" + + if not core.setting_getbool("public_serverlist") then + retval = retval .. + "button[13.85,3.95;2.25,0.5;btn_delete_favorite;".. fgettext("Delete") .. "]" + end + + retval = retval .. + "button[13.35,11;2.75,0.5;btn_mp_connect;".. fgettext("Connect") .. "]" .. + "field[7.35,10.4;5.5,0.5;te_name;" .. fgettext("Name") .. ";" ..(selected_server.playername or core.setting_get("name")) .."]" .. + "pwdfield[12.9,10.4;3.45,0.5;te_pwd;" .. fgettext("Password") ..(selected_server.playerpassword and (";"..selected_server.playerpassword) or "").. "]" .. + "textarea[7.35,6.5;8.8,2.5;;" + if menu.fav_selected ~= nil and + menu.favorites[menu.fav_selected].description ~= nil then + retval = retval .. + core.formspec_escape(menu.favorites[menu.fav_selected].description,true) + end + + retval = retval .. + ";]" + retval = retval .. "tablecolumns[" .. + "text,tooltip=Online,align=center;" .. + "text,align=center;" .. + "text,tooltip=Slots,align=center;" .. + "image,tooltip=Requires non-empty password,1=" .. e(menu.defaulttexturedir .. "server_flags_password.png") .. ";" .. + "image,tooltip=Creative,1=" .. e(menu.defaulttexturedir .. "server_flags_creative.png") .. ";" .. + "image,tooltip=Damage enabled,1=" .. e(menu.defaulttexturedir .. "server_flags_damage.png") .. ";" .. + "image,tooltip=PvP enabled,1=" .. e(menu.defaulttexturedir .. "server_flags_pvp.png") .. ";" .. + "text" .. + "]" + retval = retval .. "table[" .. + "7.1,0.35;8.8,6;favourites;" + + local render_details = 1 -- core.setting_getbool("public_serverlist") + + if menu.favorites and #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.handle_multiplayer_buttons(fields) + + 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_table_event(fields["favourites"]) + event.index = event.row + if event.type == "DCL" then + if event.index <= #menu.favorites then + selected_server = menu.favorites[event.index] + 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 + core.setting_set("address",gamedata.address) + core.setting_set("remote_port",gamedata.port) + core.start() + end + end + end + + if event.type == "CHG" then + if event.index <= #menu.favorites then + selected_server = menu.favorites[event.index] + local address = menu.favorites[event.index].address + local port = menu.favorites[event.index].port + + if address ~= nil and + port ~= nil then + core.setting_set("address",address) + core.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 = 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 + elseif fields["key_down"] and fav_idx < #menu.favorites then + fav_idx = fav_idx +1 + end + + local address = menu.favorites[fav_idx].address + local port = menu.favorites[fav_idx].port + + if address ~= nil and + port ~= nil then + core.setting_set("address",address) + core.setting_set("remote_port",port) + end + + end + + menu.fav_selected = fav_idx + 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 + menu.asyncOnlineFavourites() + else + menu.favorites = core.get_favorites("local") + end + menu.fav_selected = nil + return + 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) + menu.favorites = core.get_favorites() + menu.fav_selected = nil + + core.setting_set("address","") + core.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"] + + if selected_server.playerpassword and gamedata.password == "" then gamedata.password = selected_server.playerpassword end + + local fav_idx = core.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 + + core.setting_set("address",fields["te_address"]) + core.setting_set("remote_port",fields["te_port"]) + + core.start() + return + end +end + +-------------------------------------------------------------------------------- +-- Server tab +-------------------------------------------------------------------------------- +function tabbuilder.tab_server() + + local index = filterlist.get_current_index(worldlist, + tonumber(core.setting_get("mainmenu_last_selected_world")) + ) + + local retval = + "button[7.1,7.15;2.6,0.5;world_delete;".. fgettext("Delete") .. "]" .. + "button[9.6,7.15;2.8,0.5;world_create;".. fgettext("New") .. "]" .. + "button[12.3,7.15;2.55,0.5;world_configure;".. fgettext("Configure") .. "]" .. + "button[11,11;3.25,0.5;start_server;".. fgettext("Start Game") .. "]" .. + "label[7.1,-0.25;".. fgettext("Select World:") .. "]".. + "checkbox[7.1,7.5;cb_creative_mode;".. fgettext("Creative Mode") .. ";" .. + dump(core.setting_getbool("creative_mode")) .. "]".. + "checkbox[9.6,7.5;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. + dump(core.setting_getbool("enable_damage")) .. "]".. + "checkbox[12.3,7.5;cb_server_announce;".. fgettext("Public") .. ";" .. + dump(core.setting_getbool("server_announce")) .. "]".. + "field[7.3,9;4.5,0.5;te_playername;".. fgettext("Name") .. ";" .. + core.setting_get("name") .. "]" .. + "pwdfield[11.8,9;3.3,0.5;te_passwd;".. fgettext("Password") .. "]" + +-- TODO !!!! + local bind_addr = core.setting_get("bind_address") + if bind_addr ~= nil and bind_addr ~= "" then + retval = retval .. + "field[7.3,10.3;2.25,0.5;te_serveraddr;".. fgettext("Bind Address") .. ";" .. + core.setting_get("bind_address") .."]" .. + "field[11.8,10.3;1.25,0.5;te_serverport;".. fgettext("Port") .. ";" .. + core.setting_get("port") .."]" + else + retval = retval .. + "field[7.3,10.3;3,0.5;te_serverport;".. fgettext("Server Port") .. ";" .. + core.setting_get("port") .."]" + end + + retval = retval .. + "textlist[7.1,0.25;7.5,6.7;srv_worlds;" .. + menu.render_world_list() .. + ";" .. index .. "]" + + if not core.setting_get("menu_last_game") then + local default_game = core.setting_get("default_game") or "magichet" + core.setting_set("menu_last_game", default_game ) + end + return retval +end + +-------------------------------------------------------------------------------- +function tabbuilder.handle_server_buttons(fields) + + 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", + filterlist.get_raw_index(worldlist,core.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 + 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 = filterlist.get_raw_index(worldlist,selected) + + core.setting_set("port",gamedata.port) + if fields["te_serveraddr"] ~= nil then + core.setting_set("bind_address",fields["te_serveraddr"]) + end + + menu.update_last_game(gamedata.selected_world) + core.start() + end + end + + -- is there any more hacky way to do that? + local world_created = fields["world_create_confirm"] ~= nil or fields["world_create_cancel"] ~= nil or fields["key_enter"] ~= nil + if (fields["world_create"] ~= nil or fields["dd_mapgen"] ~= nil) and not world_created then + tabbuilder.current_tab = "dialog_create_world" + tabbuilder.is_dialog = true + tabbuilder.show_buttons = true + end + + if fields["world_delete"] ~= nil then + local selected = core.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 = core.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 + +-------------------------------------------------------------------------------- +-- Texture packs tab +-------------------------------------------------------------------------------- +function tabbuilder.tab_texture_packs() + local retval = "label[7.1,-0.25;".. fgettext("Select texture pack:") .. "]".. + "textlist[7.1,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 .. + 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[7.1,4.5;4.0,3.7;"..core.formspec_escape(screenfile or no_screenshot).."]".. + "textarea[7.35,7.5;7.5,5;;"..core.formspec_escape(infotext or "")..";]" +end + +-------------------------------------------------------------------------------- +function tabbuilder.handle_texture_pack_buttons(fields) + 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 + end +end + +-------------------------------------------------------------------------------- +-- Settings tab +-------------------------------------------------------------------------------- +function tabbuilder.tab_settings() + local tab_string = "" + local pos_x, pos_y = 7.1, 0 + local add_checkbox = function(name, config, text) + tab_string = tab_string .. + "checkbox[" .. pos_x .. "," .. pos_y .. ";" .. name .. ";".. fgettext(text) .. ";" + .. dump(core.setting_getbool(config)) .. "]" + pos_y = pos_y + 0.5 + if pos_y == 11 then + pos_y = 0 + pos_x = pos_x + 5 + end + end + -- TODO: refactor this and handle_settings_buttons + add_checkbox("cb_fancy_trees", "new_style_leaves", "Fancy trees") + add_checkbox("cb_smooth_lighting", "smooth_lighting", "Smooth Lighting") + add_checkbox("cb_enable_node_highlighting", "enable_node_highlighting", "Node Highlighting") + add_checkbox("cb_3d_clouds", "enable_3d_clouds", "3D Clouds") + add_checkbox("cb_opaque_water", "opaque_water", "Opaque Water") + add_checkbox("cb_farmesh", "farmesh", "Farmesh (dev)") + add_checkbox("cb_mipmapping", "mip_map", "Mip-Mapping") + add_checkbox("cb_anisotrophic", "anisotropic_filter", "Anisotropic Filtering") + add_checkbox("cb_bilinear", "bilinear_filter", "Bi-Linear Filtering") + add_checkbox("cb_trilinear", "trilinear_filter", "Tri-Linear Filtering") + add_checkbox("cb_shaders", "enable_shaders", "Shaders") + add_checkbox("cb_pre_ivis", "preload_item_visuals", "Preload item visuals") + add_checkbox("cb_particles", "enable_particles", "Enable Particles") + add_checkbox("cb_liquid_real", "liquid_real", "Real Liquid") + add_checkbox("cb_weather", "weather", "Weather") + add_checkbox("cb_hud_map", "hud_map", "Mini map (dev)") + add_checkbox("cb_hotbar_cycling", "hotbar_cycling", "Hotbar Cycling") + + if core.setting_getbool("enable_shaders") then + add_checkbox("cb_bumpmapping", "enable_bumpmapping", "Bumpmapping") + add_checkbox("cb_parallax", "enable_parallax_occlusion", "Parallax Occlusion") + add_checkbox("cb_generate_normalmaps", "generate_normalmaps", "Generate Normalmaps") + add_checkbox("cb_waving_water", "enable_waving_water", "Waving Water") + add_checkbox("cb_waving_leaves", "enable_waving_leaves", "Waving Leaves") + add_checkbox("cb_waving_plants", "enable_waving_plants", "Waving Plants") + end + + tab_string = tab_string .. + "button[7.1,11.5;3,0.5;btn_change_keys;".. fgettext("Change keys") .. "]" + return tab_string +end + +-------------------------------------------------------------------------------- +function tabbuilder.handle_settings_buttons(fields) + if fields["cb_fancy_trees"] then + core.setting_set("new_style_leaves", fields["cb_fancy_trees"]) + end + if fields["cb_smooth_lighting"] then + core.setting_set("smooth_lighting", fields["cb_smooth_lighting"]) + end + if fields["cb_enable_node_highlighting"] then + core.setting_set("enable_node_highlighting", fields["cb_enable_node_highlighting"]) + end + if fields["cb_3d_clouds"] then + core.setting_set("enable_3d_clouds", fields["cb_3d_clouds"]) + end + if fields["cb_opaque_water"] then + core.setting_set("opaque_water", fields["cb_opaque_water"]) + end + if fields["cb_farmesh"] then + if fields["cb_farmesh"] == "true" then + core.setting_set("farmesh", 3) + else + core.setting_set("farmesh", 0) + end + end + + if fields["cb_mipmapping"] then + core.setting_set("mip_map", fields["cb_mipmapping"]) + end + if fields["cb_anisotrophic"] then + core.setting_set("anisotropic_filter", fields["cb_anisotrophic"]) + end + if fields["cb_bilinear"] then + core.setting_set("bilinear_filter", fields["cb_bilinear"]) + end + if fields["cb_trilinear"] then + core.setting_set("trilinear_filter", fields["cb_trilinear"]) + 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 + end + if fields["cb_pre_ivis"] then + core.setting_set("preload_item_visuals", fields["cb_pre_ivis"]) + end + if fields["cb_particles"] then + core.setting_set("enable_particles", fields["cb_particles"]) + end + if fields["cb_liquid_real"] then + core.setting_set("liquid_real", fields["cb_liquid_real"]) + end + if fields["cb_weather"] then + core.setting_set("weather", fields["cb_weather"]) + end + if fields["cb_hud_map"] then + core.setting_set("hud_map", fields["cb_hud_map"]) + end + if fields["cb_hotbar_cycling"] then + core.setting_set("hotbar_cycling", fields["cb_hotbar_cycling"]) + 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"]) + end + if fields["cb_generate_normalmaps"] then + core.setting_set("generate_normalmaps", fields["cb_generate_normalmaps"]) + end + if fields["cb_waving_water"] then + core.setting_set("enable_waving_water", fields["cb_waving_water"]) + 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"]) + end + if fields["btn_change_keys"] ~= nil then + core.show_keys_menu() + end +end + +-------------------------------------------------------------------------------- +-- Credits tab +-------------------------------------------------------------------------------- +function tabbuilder.tab_credits() + return "label[7.1,0;Freeminer " .. core.get_version() .. "]" .. + "label[7.1,0.3;http://freeminer.org]" .. + "label[7.1,1.3;Contributors:]" .. + "label[7.1,1.7;https://github.com/freeminer/freeminer/graphs/contributors]" +end + + + + +-------------------------------------------------------------------------------- +-- Update functions +-------------------------------------------------------------------------------- +function menu.update() + local formspec + + -- Handle errors + if gamedata.errormessage ~= nil then + formspec = "size[12,5.2,true]" .. + "textarea[1,2;10,2;;ERROR: " .. + core.formspec_escape(gamedata.errormessage) .. + ";]".. + "button[4.5,4.2;3,0.5;btn_error_confirm;" .. fgettext("Ok") .. "]" + else + -- General size and information about what we want the formspec to be like on the menu + formspec = "size[15.5,11.625,true]" + -- Retrieve menu image from base/pack + if tabbuilder.show_buttons then + formspec = formspec .. "image[-0.35,-0.675;" .. core.formspec_escape(menu.defaulttexturedir .. "menu.png") .. "]" + end + -- Load background from base/pack + -- TODO: Allow games to set backgrounds again in menu/background.png + formspec = formspec .. "background[-50,-50;100,100;" .. core.formspec_escape(menu.defaulttexturedir .. "background.png") .. "]" + formspec = formspec .. tabbuilder.gettab() + -- Set clouds to true to avoid brown background on loading page if menu_clouds = false + -- TODO: Remove menu_clouds, use the base/pack background on loading screen? + core.set_clouds(true) + end + + core.update_formspec(formspec) +end + +-------------------------------------------------------------------------------- +function menu.update_gametype(reset) + local game = menu.lastgame() + + if reset or game == nil then + --core.set_topleft_text("") + filterlist.set_filtercriteria(worldlist,nil) + else + --core.set_topleft_text(game.name) + filterlist.set_filtercriteria(worldlist,game.id) + end +end + +-------------------------------------------------------------------------------- +function menu.update_last_game() + + local current_world = filterlist.get_raw_element(worldlist, + core.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 + core.setting_set("main_menu_last_game_idx",menu.last_game) + end +end + +-------------------------------------------------------------------------------- +-- Initial Load +-------------------------------------------------------------------------------- +function menu.init() + --init gamedata + gamedata.worldindex = 0 + + worldlist = filterlist.create( + core.get_worlds, + compare_worlds, + function(element,uid) + if element.name == uid then + return true + end + return false + end, --unique id compare fct + function(element,gameid) + if element.gameid == gameid then + return true + end + return false + end --filter fct + ) + + filterlist.add_sort_mechanism(worldlist,"alphabetic",sort_worlds_alphabetic) + filterlist.set_sortmode(worldlist,"alphabetic") + + + --init menu data + gamemgr.update_gamelist() + + menu.last_game = tonumber(core.setting_get("main_menu_last_game_idx")) + + if type(menu.last_game) ~= "number" then + menu.last_game = 1 + end + + if core.setting_getbool("public_serverlist") then + menu.asyncOnlineFavourites() + else + menu.favorites = core.get_favorites("local") + end + + menu.defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" .. + DIR_DELIM .. "pack" .. DIR_DELIM +end + +-------------------------------------------------------------------------------- +function tabbuilder.init() + tabbuilder.tabfuncs = { + singleplayer = tabbuilder.tab_singleplayer, + multiplayer = tabbuilder.tab_multiplayer, + server = tabbuilder.tab_server, + texture_packs = tabbuilder.tab_texture_packs, + settings = tabbuilder.tab_settings, + 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 = core.setting_get("main_menu_tab") + + if tabbuilder.current_tab == nil or + tabbuilder.current_tab == "" then + tabbuilder.current_tab = "singleplayer" + core.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("Multiplayer")}) + table.insert(tabbuilder.current_buttons,{name="server", caption=fgettext("Create Server")}) + table.insert(tabbuilder.current_buttons,{name="texture_packs", caption=fgettext("Texture Packs")}) + + if core.setting_getbool("main_menu_game_mgr") then + table.insert(tabbuilder.current_buttons,{name="game_mgr", caption=fgettext("Games")}) + end + + if core.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="settings", caption=fgettext("Settings")}) + 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 + + + +-------------------------------------------------------------------------------- +-- Initialize callbacks +-------------------------------------------------------------------------------- +core.button_handler = function(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 + menu.update() + else + tabbuilder.skipformupdate = false + 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 + +-------------------------------------------------------------------------------- +core.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 = core.setting_get("main_menu_tab") + menu.update_gametype() + menu.update() + else + core.close() + end + end + + if event == "Refresh" then + menu.update() + end +end + +-------------------------------------------------------------------------------- +-- Menu Startup +-------------------------------------------------------------------------------- +menu.init() +tabbuilder.init() +modstore.init() + +menubar.refresh() + + +core.sound_play("main_menu", true) + +menu.update() diff --git a/builtin/mainmenu/fm_modmgr.lua b/builtin/mainmenu/fm_modmgr.lua new file mode 100644 index 000000000..ff0883910 --- /dev/null +++ b/builtin/mainmenu/fm_modmgr.lua @@ -0,0 +1,1120 @@ +--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. + +-------------------------------------------------------------------------------- +function get_mods(path,retval,modpack) + local mods = core.get_dirlist(path, true) + + for i=1, #mods, 1 do + if mods[i]:sub(1,1) ~= "." then + local toadd = {} + local modpackfile = nil + + toadd.name = mods[i] + toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM + if modpack ~= nil and + modpack ~= "" then + toadd.modpack = modpack + else + local filename = path .. DIR_DELIM .. mods[i] .. DIR_DELIM .. "modpack.txt" + local error = nil + modpackfile,error = io.open(filename,"r") + end + + if modpackfile ~= nil then + modpackfile:close() + toadd.is_modpack = true + table.insert(retval,toadd) + get_mods(path .. DIR_DELIM .. mods[i],retval,mods[i]) + else + table.insert(retval,toadd) + end + end + end +end + +--modmanager implementation +modmgr = {} + +-------------------------------------------------------------------------------- +function modmgr.extract(modfile) + if modfile.type == "zip" then + local tempfolder = os.tempfolder() + + if tempfolder ~= nil and + tempfolder ~= "" then + core.create_dir(tempfolder) + if core.extract_zip(modfile.name,tempfolder) then + return tempfolder + end + end + end + return nil +end + +------------------------------------------------------------------------------- +function modmgr.getbasefolder(temppath) + + if temppath == nil then + return { + type = "invalid", + path = "" + } + end + + local testfile = io.open(temppath .. DIR_DELIM .. "init.lua","r") + if testfile ~= nil then + testfile:close() + return { + type="mod", + path=temppath + } + end + + testfile = io.open(temppath .. DIR_DELIM .. "modpack.txt","r") + if testfile ~= nil then + testfile:close() + return { + type="modpack", + path=temppath + } + end + + local subdirs = core.get_dirlist(temppath,true) + + --only single mod or modpack allowed + if #subdirs ~= 1 then + return { + type = "invalid", + path = "" + } + end + + testfile = + io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."init.lua","r") + if testfile ~= nil then + testfile:close() + return { + type="mod", + path= temppath .. DIR_DELIM .. subdirs[1] + } + end + + testfile = + io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."modpack.txt","r") + if testfile ~= nil then + testfile:close() + return { + type="modpack", + path=temppath .. DIR_DELIM .. subdirs[1] + } + end + + return { + type = "invalid", + path = "" + } +end + +-------------------------------------------------------------------------------- +function modmgr.isValidModname(modpath) + if modpath:find("-") ~= nil then + return false + end + + return true +end + +-------------------------------------------------------------------------------- +function modmgr.parse_register_line(line) + local pos1 = line:find("\"") + local pos2 = nil + if pos1 ~= nil then + pos2 = line:find("\"",pos1+1) + end + + if pos1 ~= nil and pos2 ~= nil then + local item = line:sub(pos1+1,pos2-1) + + if item ~= nil and + item ~= "" then + local pos3 = item:find(":") + + if pos3 ~= nil then + local retval = item:sub(1,pos3-1) + if retval ~= nil and + retval ~= "" then + return retval + end + end + end + end + return nil +end + +-------------------------------------------------------------------------------- +function modmgr.parse_dofile_line(modpath,line) + local pos1 = line:find("\"") + local pos2 = nil + if pos1 ~= nil then + pos2 = line:find("\"",pos1+1) + end + + if pos1 ~= nil and pos2 ~= nil then + local filename = line:sub(pos1+1,pos2-1) + + if filename ~= nil and + filename ~= "" and + filename:find(".lua") then + return modmgr.identify_modname(modpath,filename) + end + end + return nil +end + +-------------------------------------------------------------------------------- +function modmgr.identify_modname(modpath,filename) + local testfile = io.open(modpath .. DIR_DELIM .. filename,"r") + if testfile ~= nil then + local line = testfile:read() + + while line~= nil do + local modname = nil + + if line:find("register_tool") or + line:find("register_craftitem") or + line:find("register_node") then + modname = modmgr.parse_register_line(line) + end + + if line:find("dofile") then + modname = modmgr.parse_dofile_line(modpath,line) + end + + if modname ~= nil then + testfile:close() + return modname + end + + line = testfile:read() + end + testfile:close() + end + + 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 = + "label[7.1,-0.25;".. fgettext("Installed Mods:") .. "]" .. + "textlist[7.1,0.25;8,4;modlist;" .. + modmgr.render_modlist(modmgr.global_mods) .. + ";" .. modmgr.selected_mod .. "]" + + retval = retval .. +-- 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[7.1,4.5;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[7.1,5;3,2;" .. core.formspec_escape(modscreenshot) .. "]" + .. "label[10.1,5.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 = core.splittext(descriptiontext,42) + descriptionfile:close() + else + descriptionlines = {} + table.insert(descriptionlines,fgettext("No mod description available")) + end + + retval = retval .. + "label[7.1,6.7;".. fgettext("Mod information:") .. "]" .. + "textlist[7.1,7.2;8,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.6.85;2,0.5;btn_mod_mgr_rename_modpack;" .. + fgettext("Rename") .. "]" + retval = retval .. "button[7.1,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[7.1,9.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 = "" + + if render_list == nil then + if modmgr.global_mods == nil then + modmgr.refresh_globals() + end + render_list = modmgr.global_mods + end + + local list = filterlist.get_list(render_list) + local last_modpack = nil + + for i,v in ipairs(list) do + if retval ~= "" then + retval = retval .."," + end + + local color = "" + + if v.is_modpack then + local rawlist = filterlist.get_raw_list(render_list) + + local all_enabled = true + for j=1,#rawlist,1 do + if rawlist[j].modpack == list[i].name and + rawlist[j].enabled ~= true then + all_enabled = false + break + end + end + + if all_enabled == false then + color = mt_color_grey + else + color = mt_color_dark_green + end + end + + if v.typ == "game_mod" then + color = mt_color_blue + else + if v.enabled then + color = mt_color_green + end + end + + retval = retval .. color + if v.modpack ~= nil then + retval = retval .. " " + end + retval = retval .. v.name + end + + return retval +end + +-------------------------------------------------------------------------------- +function modmgr.dialog_configure_world() + modmgr.precheck() + + local worldspec = core.get_worlds()[modmgr.world_config_selected_world] + local mod = filterlist.get_list(modmgr.modlist)[modmgr.world_config_selected_mod] + + local retval = + "size[11,6.5,true]" .. + "label[0.5,-0.25;" .. fgettext("World:") .. "]" .. + "label[1.75,-0.25;" .. worldspec.name .. "]" + + if modmgr.hide_gamemods then + retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]" + else + retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]" + end + + if modmgr.hide_modpackcontents then + retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]" + else + retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]" + end + + if mod == nil then + mod = {name=""} + end + retval = retval .. + "label[0,0.45;" .. fgettext("Mod:") .. "]" .. + "label[0.75,0.45;" .. mod.name .. "]" .. + "label[0,1;" .. fgettext("Depends:") .. "]" .. + "textlist[0,1.5;5,4.25;world_config_depends;" .. + modmgr.get_dependencies(mod.path) .. ";0]" .. + "button[9.25,6.35;2,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" .. + "button[7.4,6.35;2,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]" + + if mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then + if mod.is_modpack then + local rawlist = filterlist.get_raw_list(modmgr.modlist) + + local all_enabled = true + for j=1,#rawlist,1 do + if rawlist[j].modpack == mod.name and + rawlist[j].enabled ~= true then + all_enabled = false + break + end + end + + if all_enabled == false then + retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]" + else + retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_disable;" .. fgettext("Disable MP") .. "]" + end + else + if mod.enabled then + retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";true]" + else + retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";false]" + end + end + end + + retval = retval .. + "button[8.5,-0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" .. + "textlist[5.5,0.5;5.5,5.75;world_config_modlist;" + + retval = retval .. modmgr.render_modlist(modmgr.modlist) + + retval = retval .. ";" .. modmgr.world_config_selected_mod .."]" + + return retval +end + +-------------------------------------------------------------------------------- +function modmgr.handle_buttons(tab,fields) + + local retval = nil + + if tab == "mod_mgr" then + retval = modmgr.handle_modmgr_buttons(fields) + end + + if tab == "dialog_rename_modpack" then + retval = modmgr.handle_rename_modpack_buttons(fields) + end + + if tab == "dialog_delete_mod" then + retval = modmgr.handle_delete_mod_buttons(fields) + end + + if tab == "dialog_configure_world" then + retval = modmgr.handle_configure_world_buttons(fields) + end + + return retval +end + +-------------------------------------------------------------------------------- +function modmgr.get_dependencies(modfolder) + local toadd = "" + if modfolder ~= nil then + local filename = modfolder .. + DIR_DELIM .. "depends.txt" + + local dependencyfile = io.open(filename,"r") + + if dependencyfile then + local dependency = dependencyfile:read("*l") + while dependency do + if toadd ~= "" then + toadd = toadd .. "," + end + toadd = toadd .. dependency + dependency = dependencyfile:read() + end + dependencyfile:close() + end + end + + return toadd +end + + +-------------------------------------------------------------------------------- +function modmgr.get_worldconfig(worldpath) + local filename = worldpath .. + DIR_DELIM .. "world.mt" + + local worldfile = Settings(filename) + + local worldconfig = {} + worldconfig.global_mods = {} + worldconfig.game_mods = {} + + for key,value in pairs(worldfile:to_table()) do + if key == "gameid" then + worldconfig.id = value + else + worldconfig.global_mods[key] = core.is_yes(value) + end + end + + --read gamemods + local gamespec = gamemgr.find_by_gameid(worldconfig.id) + gamemgr.get_game_mods(gamespec, worldconfig.game_mods) + + 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 = core.explode_textlist_event(fields["modlist"]) + modmgr.selected_mod = event.index + end + + if fields["btn_mod_mgr_install_local"] ~= nil then + core.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) + local modfile = modmgr.identify_filetype(modfilename) + local modpath = modmgr.extract(modfile) + + if modpath == nil then + gamedata.errormessage = fgettext("Install Mod: file: \"$1\"", modfile.name) .. + fgettext("\nInstall Mod: unsupported filetype \"$1\" or broken archive", modfile.type) + return + end + + + local basefolder = modmgr.getbasefolder(modpath) + + if basefolder.type == "modpack" then + local clean_path = nil + + if basename ~= nil then + clean_path = "mp_" .. basename + end + + if clean_path == nil then + clean_path = get_last_folder(cleanup_path(basefolder.path)) + end + + if clean_path ~= nil 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 + gamedata.errormessage = fgettext("Install Mod: unable to find suitable foldername for modpack $1", modfilename) + end + end + + if basefolder.type == "mod" then + local targetfolder = basename + + if targetfolder == nil then + targetfolder = modmgr.identify_modname(basefolder.path,"init.lua") + end + + --if heuristic failed try to use current foldername + if targetfolder == nil then + targetfolder = get_last_folder(basefolder.path) + end + + if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then + 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 + + 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 = core.get_modpath() .. DIR_DELIM .. 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 = 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 = core.setting_get("main_menu_tab") + } +end +-------------------------------------------------------------------------------- +function modmgr.handle_configure_world_buttons(fields) + if fields["world_config_modlist"] ~= nil then + local event = core.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 = core.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 core.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 core.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 = core.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 + core.log("error", "Failed to write world config file") + end + + modmgr.modlist = nil + modmgr.worldconfig = nil + + return { + is_dialog = false, + show_buttons = true, + current_tab = core.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 = core.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) + [core.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 ~= core.get_modpath() then + if not core.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 = core.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 = {} + + local global_mods = {} + local game_mods = {} + + --read global mods + local modpath = core.get_modpath() + + if modpath ~= nil and + modpath ~= "" then + get_mods(modpath,global_mods) + end + + for i=1,#global_mods,1 do + global_mods[i].typ = "global_mod" + table.insert(retval,global_mods[i]) + end + + --read game mods + local gamespec = gamemgr.find_by_gameid(data.gameid) + gamemgr.get_game_mods(gamespec, game_mods) + + for i=1,#game_mods,1 do + game_mods[i].typ = "game_mod" + table.insert(retval,game_mods[i]) + end + + if data.worldpath == nil then + return retval + end + + --read world mod configuration + local filename = data.worldpath .. + DIR_DELIM .. "world.mt" + + local worldfile = Settings(filename) + + for key,value in pairs(worldfile:to_table()) do + if key:sub(1, 9) == "load_mod_" then + key = key:sub(10) + local element = nil + for i=1,#retval,1 do + if retval[i].name == key then + element = retval[i] + break + end + end + if element ~= nil then + element.enabled = core.is_yes(value) + else + core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found") + end + end + end + + return retval +end + +-------------------------------------------------------------------------------- +function modmgr.init_worldconfig() + modmgr.precheck() + local worldspec = core.get_worlds()[modmgr.world_config_selected_world] + + if worldspec ~= nil then + --read worldconfig + modmgr.worldconfig = modmgr.get_worldconfig(worldspec.path) + + if modmgr.worldconfig.id == nil or + modmgr.worldconfig.id == "" then + modmgr.worldconfig = nil + return false + end + + modmgr.modlist = filterlist.create( + modmgr.preparemodlist, --refresh + modmgr.comparemod, --compare + function(element,uid) --uid match + if element.name == uid then + return true + end + end, + function(element,criteria) + if criteria.hide_game and + element.typ == "game_mod" then + return false + end + + if criteria.hide_modpackcontents and + element.modpack ~= nil then + return false + end + return true + end, --filter + { worldpath= worldspec.path, + gameid = worldspec.gameid } + ) + + filterlist.set_filtercriteria(modmgr.modlist, { + hide_game=modmgr.hide_gamemods, + hide_modpackcontents= modmgr.hide_modpackcontents + }) + filterlist.add_sort_mechanism(modmgr.modlist, "alphabetic", sort_mod_list) + filterlist.set_sortmode(modmgr.modlist, "alphabetic") + + return true + end + + return false +end + +-------------------------------------------------------------------------------- +function modmgr.comparemod(elem1,elem2) + if elem1 == nil or elem2 == nil then + return false + end + if elem1.name ~= elem2.name then + return false + end + if elem1.is_modpack ~= elem2.is_modpack then + return false + end + if elem1.typ ~= elem2.typ then + return false + end + if elem1.modpack ~= elem2.modpack then + return false + end + + if elem1.path ~= elem2.path then + return false + end + + 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) + + if modmgr.global_mods == nil then + modmgr.refresh_globals() + end + + if filterlist.raw_index_by_uid(modmgr.global_mods,basename) > 0 then + return true + end + + return false +end + +-------------------------------------------------------------------------------- +function modmgr.get_global_mod(idx) + + if modmgr.global_mods == nil then + return nil + end + + if idx == nil or idx < 1 or idx > filterlist.size(modmgr.global_mods) then + return nil + end + + return filterlist.get_list(modmgr.global_mods)[idx] +end + +-------------------------------------------------------------------------------- +function modmgr.refresh_globals() + modmgr.global_mods = filterlist.create( + modmgr.preparemodlist, --refresh + modmgr.comparemod, --compare + function(element,uid) --uid match + if element.name == uid then + return true + end + end, + nil, --filter + {} + ) + filterlist.add_sort_mechanism(modmgr.global_mods, "alphabetic", sort_mod_list) + filterlist.set_sortmode(modmgr.global_mods, "alphabetic") +end + +-------------------------------------------------------------------------------- +function modmgr.identify_filetype(name) + + if name:sub(-3):lower() == "zip" then + return { + name = name, + type = "zip" + } + end + + if name:sub(-6):lower() == "tar.gz" or + name:sub(-3):lower() == "tgz"then + return { + name = name, + type = "tgz" + } + end + + if name:sub(-6):lower() == "tar.bz2" then + return { + name = name, + type = "tbz" + } + end + + if name:sub(-2):lower() == "7z" then + return { + name = name, + type = "7z" + } + end + + return { + name = name, + type = "ukn" + } +end diff --git a/builtin/mainmenu/gamemgr.lua b/builtin/mainmenu/gamemgr.lua index 24b5861b2..b6faa71d9 100644 --- a/builtin/mainmenu/gamemgr.lua +++ b/builtin/mainmenu/gamemgr.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify diff --git a/builtin/mainmenu/init_old.lua b/builtin/mainmenu/init_old.lua deleted file mode 100644 index 904caa900..000000000 --- a/builtin/mainmenu/init_old.lua +++ /dev/null @@ -1,164 +0,0 @@ ---multicraft ---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! - -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 - -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 .. "tab_credits.lua") -dofile(menupath .. DIR_DELIM .. "tab_mods.lua") -dofile(menupath .. DIR_DELIM .. "tab_settings.lua") ---if PLATFORM ~= "Android" then - 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_multiplayer.lua") - dofile(menupath .. DIR_DELIM .. "tab_server.lua") - dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua") - dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua") - dofile(menupath .. DIR_DELIM .. "textures.lua") ---else --- dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua") ---end - --------------------------------------------------------------------------------- -local function main_event_handler(tabview, event) - if event == "MenuQuit" then - core.close() - end - return true -end - --------------------------------------------------------------------------------- -local function init_globals() - -- Init gamedata - gamedata.worldindex = 0 - - - if PLATFORM ~= "Android" then - menudata.worldlist = filterlist.create( - core.get_worlds, - compare_worlds, - -- Unique id comparison function - function(element, uid) - return element.name == uid - end, - -- Filter function - function(element, gameid) - return element.gameid == gameid - end - ) - - menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic) - menudata.worldlist:set_sortmode("alphabetic") - - if not core.setting_get("menu_last_game") then - local default_game = core.setting_get("default_game") or "multicraft" - core.setting_set("menu_last_game", default_game ) - end - - mm_texture.init() - else - local world_list = core.get_worlds() - - local found_singleplayerworld = false - - for i,world in pairs(world_list) do - if world.name == "singleplayerworld" then - found_singleplayerworld = true - gamedata.worldindex = i - break - end - end - - if not found_singleplayerworld then - core.create_world("singleplayerworld", 1) - - local world_list = core.get_worlds() - - for i,world in pairs(world_list) do - if world.name == "singleplayerworld" then - gamedata.worldindex = i - break - end - end - end - end - - -- Create main tabview - local tv_main = tabview_create("maintab",{x=12,y=5.2},{x=0,y=0}) - if PLATFORM ~= "Android" then - tv_main:set_autosave_tab(true) - end - if PLATFORM ~= "Android" then - tv_main:add(tab_singleplayer) - tv_main:add(tab_multiplayer) - tv_main:add(tab_server) - else - tv_main:add(tab_simple_main) - end - tv_main:add(tab_settings) - if PLATFORM ~= "Android" then - tv_main:add(tab_texturepacks) - end - tv_main:add(tab_mods) - tv_main:add(tab_credits) - - tv_main:set_global_event_handler(main_event_handler) - - tv_main:set_fixed_size(false) - - if not (PLATFORM == "Android") then - tv_main:set_tab(core.setting_get("maintab_LAST")) - end - ui.set_default("maintab") - tv_main:show() - - -- Create modstore ui - if PLATFORM == "Android" then - modstore.init({x=12, y=6}, 3, 2) - else - modstore.init({x=12, y=8}, 4, 3) - end - - ui.update() - - core.sound_play("main_menu", true) -end - -init_globals() - diff --git a/builtin/mainmenu/menubar.lua b/builtin/mainmenu/menubar.lua new file mode 100644 index 000000000..8a7eaf57f --- /dev/null +++ b/builtin/mainmenu/menubar.lua @@ -0,0 +1,80 @@ +--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 + core.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 .. ",11.2;1.165,1.175;" .. + core.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 4f1b65447..f2938685e 100644 --- a/builtin/mainmenu/modmgr.lua +++ b/builtin/mainmenu/modmgr.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify @@ -195,16 +195,16 @@ function modmgr.identify_modname(modpath,filename) while line~= nil do local modname = nil - if line:find("multicraft.register_tool") then + if line:find("minetest.register_tool") then modname = modmgr.parse_register_line(line) end - if line:find("multicraft.register_craftitem") then + if line:find("minetest.register_craftitem") then modname = modmgr.parse_register_line(line) end - if line:find("multicraft.register_node") then + if line:find("minetest.register_node") then modname = modmgr.parse_register_line(line) end @@ -321,10 +321,8 @@ function modmgr.get_worldconfig(worldpath) for key,value in pairs(worldfile:to_table()) do if key == "gameid" then worldconfig.id = value - elseif key:sub(0, 9) == "load_mod_" then - worldconfig.global_mods[key] = core.is_yes(value) else - worldconfig[key] = value + worldconfig.global_mods[key] = core.is_yes(value) end end diff --git a/builtin/mainmenu/modstore.lua b/builtin/mainmenu/modstore.lua new file mode 100644 index 000000000..391b5806e --- /dev/null +++ b/builtin/mainmenu/modstore.lua @@ -0,0 +1,615 @@ +--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 = 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 +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;" .. core.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 index d459d15b1..a4c4e5117 100644 --- a/builtin/mainmenu/store.lua +++ b/builtin/mainmenu/store.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify @@ -24,591 +24,595 @@ 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.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.basetexturedir = core.get_texturepath() .. DIR_DELIM .. "base" .. + DIR_DELIM .. "pack" .. DIR_DELIM - modstore.lastmodtitle = "" - modstore.last_search = "" + 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() + 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.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.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 - ) + 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.current_list = nil - modstore.tv_store = tabview_create("modstore",size,{x=0,y=0}) + modstore.tv_store = tabview_create("modstore",size,{x=0,y=0}) - modstore.tv_store:set_global_event_handler(modstore.handle_events) + 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 = "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 - } - ) + 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 + for i=1,#modstore.tabnames,1 do + if modstore.tabnames[i] == name then + return i + end + end - return 1 + 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 $1, please wait...", data.title) .. "]" - 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(this) - else - this.parent:show() - this:delete() - modstore.lastmodtitle = "" - end + 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 - return true - end + this:delete() + return true + end - return false - end, - nil) + return false + end, + nil, + modstore.tv_store) - new_dlg:set_parent(modstore.tv_store) - modstore.tv_store:hide() - new_dlg.data.title = title - new_dlg:show() + new_dlg.data.title = title + new_dlg:show() end -------------------------------------------------------------------------------- -- @function [parent=#modstore] successfulldialog -function modstore.successfulldialog(downloading_dlg) - 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 .. "image_button[2.2,1.5;1.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_confirm_mod_successfull;" .. fgettext("Ok") .. "]" - return retval - end, - function(this,fields) - if fields["btn_confirm_mod_successfull"] ~= nil then - this.parent:show() - downloading_dlg:delete() - this:delete() +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 .. "]" - return true - end - return false - end, - nil) + retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]" + retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]" - new_dlg:set_parent(modstore.tv_store) - modstore.tv_store:hide() - new_dlg:show() + end + retval = retval .. "image_button[2.5,1.5;1,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_confirm_mod_successfull;" .. fgettext("ok") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + 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_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 (IMPORTANT has to be defined AFTER rating) + if details.versions ~= nil and + #details.versions > 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 + 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 .."image_button[9.1," .. buttony .. ";2.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_install_mod_" .. details.id .. ";" + if details.basename then + --install button + local buttony = ypos + 1.2 + retval = retval .."image_button[9.1," .. buttony .. ";2.5,0.5;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_install_mod_" .. details.id .. ";" - if modmgr.mod_exists(details.basename) then - retval = retval .. fgettext("re-Install") .."]" - else - retval = retval .. fgettext("Install") .."]" - end - end + if modmgr.mod_exists(details.basename) then + retval = retval .. fgettext("re-Install") ..";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + else + retval = retval .. fgettext("Install") ..";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + end + end - return retval + return retval end -------------------------------------------------------------------------------- --@function [parent=#modstore] getmodlist function modstore.getmodlist(list,yoffset) - modstore.current_list = list + modstore.current_list = list - if yoffset == nil then - yoffset = 0 - end + if yoffset == nil then + yoffset = 0 + end - local sb_y_start = 0.2 + yoffset - local sb_y_end = (modstore.modsperpage * 1.75) + ((modstore.modsperpage-1) * 0.15) - local close_button = "image_button[4," .. (sb_y_end + 0.3 + yoffset) .. - ";4,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_close;" .. fgettext("Close store") .. "]" + local sb_y_start = 0.2 + yoffset + local sb_y_end = (modstore.modsperpage * 1.75) + ((modstore.modsperpage-1) * 0.15) + local close_button = "image_button[4," .. (sb_y_end + 0.3 + yoffset) .. + ";4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_close;" .. fgettext("Close store") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - if #list.data == 0 then - return close_button - end + 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 .. "image_button[11.6," .. (sb_y_start) - .. ";0.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_page_up;^]" - scrollbar = scrollbar .. "image_button[11.6," .. (sb_y_start + sb_y_end - 0.5) - .. ";0.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_page_down;v]" + 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 .. "image_button[11.6," .. (sb_y_start) + .. ";0.5,0.5;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_page_up;^;true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + scrollbar = scrollbar .. "image_button[11.6," .. (sb_y_start + sb_y_end - 0.5) + .. ";0.5,0.5;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_page_down;v;true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - local retval = "" + local retval = "" - local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage + local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage - if (endmod > #list.data) then - endmod = #list.data - end + 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 + 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 + 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 + 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 + retval = retval .. modstore.getshortmodinfo(screenshot_ypos, + list.data[i], + details) + end + end - return retval .. scrollbar .. close_button + return retval .. scrollbar .. close_button end -------------------------------------------------------------------------------- --@function [parent=#modstore] getsearchpage function modstore.getsearchpage(tabview, name, tabdata) - local retval = "" - local search = "" + local retval = "" + local search = "" - if modstore.last_search ~= nil then - search = modstore.last_search - end + if modstore.last_search ~= nil then + search = modstore.last_search + end - retval = retval .. - "image_button[9.5,0.2;2.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_search;".. fgettext("Search") .. "]" .. - "field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]" + retval = retval .. + "image_button[9.5,0.2;2.5,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore_search;".. fgettext("Search") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]" - retval = retval .. - modstore.getmodlist( - modstore.currentlist, - 1.75) + retval = retval .. + modstore.getmodlist( + modstore.currentlist, + 1.75) - return retval; + return retval; end -------------------------------------------------------------------------------- --@function [parent=#modstore] unsorted_tab function modstore.unsorted_tab() - return modstore.getmodlist(modstore.modlist_unsorted) + 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), - } + 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 index 0d9015be1..ad34a41b4 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify @@ -18,53 +18,63 @@ -------------------------------------------------------------------------------- tab_credits = { - name = "credits", - caption = fgettext("Credits"), - cbf_formspec = function (tabview, name, tabdata) - local logofile = defaulttexturedir .. "logo.png" - return "label[0.5,3.2;multicraft " .. core.get_version() .. "]" .. - "label[0.5,3.5;http://multicraft.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 ," .. - "Lisa Milne (darkrose) ,".. - "Maciej Kasatkin (RealBadAngel) ,".. - "sfan5 ,".. - "kahrl ,".. - "sapier,".. - "ShadowNinja ,".. - "Nathanael Courant (Nore/Novatux) ,".. - "BlockMen,".. - "Craig Robbins (Zeno),".. - "Loic Blot (nerzhul/nrz),".. - "paramat,".. - ",".. - "#FFFF00" .. fgettext("Active Contributors") .. "," .. - "SmallJoker ," .. - "est31 ," .. - "gregorycu,".. - "Andrew Ward (rubenwardy) ," .. - "TriBlade9 ,".. - "Zefram ,".. - "," .. - "#FFFF00" .. fgettext("Previous Contributors") .. "," .. - "Vanessa Ezekowitz (VanessaE) ,".. - "Jurgen Doser (doserj) ,".. - "Jeija ,".. - "MirceaKitsune ,".. - "dannydark ,".. - "0gb.us <0gb.us@0gb.us>,".. - "proller ,".. - "Ilya Zhuravlev (xyz) ,".. - "Guiseppe Bilotta (Oblomov) ,".. - "Jonathan Neuschafer ,".. - "Nils Dagsson Moskopp (erlehmann) ,".. - "Constantin Wenger (SpeedProg) ,".. - "matttpt ,".. - "JacobF ,".. - ";0;true]" - end - } + name = "credits", + caption = fgettext("Credits"), + cbf_formspec = function (tabview, name, tabdata) + local logofile = defaulttexturedir .. "logo.png" + return "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_cancel;".. fgettext("OK") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "label[3.5,9.75;Magichet 1.0 (based on FM " .. core.get_version() .. ")]" .. + "image[0.25,9;2,2;"..core.formspec_escape(logofile).."]".. + "textlist[0,2.0;15.8,6.25;list_credits;" .. + "#FFFF00" .. fgettext("Core Developers") .."," .. + " Perttu Ahola (celeron55) ,".. + " Ryan Kwolek (kwolekr) ,".. + " kahrl ,".. + " proller ,".. + " PilzAdam ," .. + " ShadowNinja ,".. + " sfan5 ,".. + " ...,".. + ",".. + "#FFFF00" .. fgettext("Active Contributors") .. "," .. + " sapier,".. + " Craig Robbins (Zeno) ,".. + " kilbith,".. + " paramat,".. + " ...,".. + ",".. + "#FFFF00" .. fgettext("Magichet Developers") .. "," .. + " 4aiman Konsorumaniakku <4aiman@inbox.ru>,".. + " ...,".. + "," .. + "#FFFF00" .. fgettext("Previous Contributors") .. "," .. + " Vanessa Ezekowitz (VanessaE) ,".. + " Jurgen Doser (doserj) ,".. + " Jeija ,".. + " MirceaKitsune ,".. + " dannydark ,".. + " 0gb.us <0gb.us@0gb.us>,".. + " Ilya Zhuravlev (xyz) ,".. + " Guiseppe Bilotta (Oblomov) ,".. + " Jonathan Neuschafer ,".. + " Nils Dagsson Moskopp (erlehmann) ,".. + " Constantin Wenger (SpeedProg) ,".. + " matttpt ,".. + " JacobF ,".. + " ...,".. + ";0;true]" + end, + cbf_button_handler = function(tabview, fields, name, tabdata) + if fields["btn_cancel"] ~= nil then + tabview:hide() + tabview.parent:show() + return true + end + return false + end + } diff --git a/builtin/mainmenu/tab_help.lua b/builtin/mainmenu/tab_help.lua new file mode 100644 index 000000000..c1f553a40 --- /dev/null +++ b/builtin/mainmenu/tab_help.lua @@ -0,0 +1,59 @@ +--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_help = { + name = "help", + caption = fgettext("Help"), + cbf_formspec = function (tabview, name, tabdata) + local logofile = defaulttexturedir .. "logo.png" + return "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_cancel;".. fgettext("OK") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "label[3.5,9.75;Magichet 1.0 (based on FM " .. core.get_version() .. ")]" .. + "image[0.25,9;2,2;"..core.formspec_escape(logofile).."]".. + + "textlist[0,2;15.8,6.25;list_help;" .. + "#FFFF00How to begin to play (ENG)," .. + " - Press and hold to dig a block,".. + " - Doubletap to place a block,".. + " - To split a stack 'long pess' on it and,".. + " w/o releasing it tap a separate inventory cell,".. + ",".. + ",".. + "#FFFF00Как начать играть (RUS)," .. + " - Долгое нажатие = сломать блок,".. + " - Двойное нажатие = поставить блок,".. + " - Для разделения стака на части,".. + " нажмите на стак и удерживая его,".. + " нажмите вторым пальцем на свободной,".. + " ячейке интвентаря".. + ";0;true]" + end, + cbf_button_handler = function(tabview, fields, name, tabdata) + if fields["btn_cancel"] ~= nil then + tabview:hide() + tabview.parent:show() + return true + end + return false + end + } diff --git a/builtin/mainmenu/tab_mods.lua b/builtin/mainmenu/tab_mods.lua index 64ed9fcc7..9062f1271 100644 --- a/builtin/mainmenu/tab_mods.lua +++ b/builtin/mainmenu/tab_mods.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -18,152 +18,152 @@ -------------------------------------------------------------------------------- local function get_formspec(tabview, name, tabdata) - if modmgr.global_mods == nil then - modmgr.refresh_globals() - end + if modmgr.global_mods == nil then + modmgr.refresh_globals() + end - if tabdata.selected_mod == nil then - tabdata.selected_mod = 1 - end + if tabdata.selected_mod == nil then + tabdata.selected_mod = 1 + end - local retval = - "label[0.05,-0.25;".. fgettext("Installed Mods:") .. "]" .. - "textlist[0,0.25;5.1,4.35;modlist;" .. - modmgr.render_modlist(modmgr.global_mods) .. - ";" .. tabdata.selected_mod .. "]" + local retval = + "label[0.05,-0.25;".. fgettext("Installed Mods:") .. "]" .. + "textlist[0,0.25;5.1,4.35;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 --- "image_button[0.75,4.85;1.8,0.5;btn_mod_mgr_install_local;".. fgettext("Local install") .. "]" .. - "image_button[0,4.85;5.25,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore;".. fgettext("Online mod repository") .. "]" + 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") .. "]" .. + "image_button[0,4.85;5.25,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_modstore;".. fgettext("Online mod repository") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" - local selected_mod = nil + 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 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 + 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 + --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 = defaulttexturedir .. "no_screenshot.png" - 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 .. "]" + 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") + 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 + 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;" + 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 + for i=1,#descriptionlines,1 do + retval = retval .. core.formspec_escape(descriptionlines[i]) .. "," + end - if selected_mod.is_modpack then - retval = retval .. ";0]" .. - "image_button[10,4.85;2,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mod_mgr_rename_modpack;" .. - fgettext("Rename") .. "]" - retval = retval .. "image_button[5.5,4.85;4.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mod_mgr_delete_mod;" - .. fgettext("Uninstall selected modpack") .. "]" - else - --show dependencies + if selected_mod.is_modpack then + retval = retval .. ";0]" .. + "image_button[10,4.85;2,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mod_mgr_rename_modpack;" .. + fgettext("Rename") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + retval = retval .. "image_button[5.5,4.85;4.5,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mod_mgr_delete_mod;" + .. fgettext("Uninstall selected modpack") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + else + --show dependencies - retval = retval .. "," .. fgettext("Depends:") .. "," + retval = retval .. ",Depends:," - local toadd = modmgr.get_dependencies(selected_mod.path) + local toadd = modmgr.get_dependencies(selected_mod.path) - retval = retval .. toadd .. ";0]" + retval = retval .. toadd .. ";0]" - retval = retval .. "image_button[5.5,4.85;4.5,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mod_mgr_delete_mod;" - .. fgettext("Uninstall selected mod") .. "]" - end - end - return retval + retval = retval .. "image_button[5.5,4.85;4.5,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mod_mgr_delete_mod;" + .. fgettext("Uninstall selected mod") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + 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["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_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_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_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["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 + 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 + return false end -------------------------------------------------------------------------------- tab_mods = { - name = "mods", - caption = fgettext("Mods"), - cbf_formspec = get_formspec, - cbf_button_handler = handle_buttons, - on_change = gamemgr.update_gamelist + 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 index d7e9f100f..0cf3f903b 100644 --- a/builtin/mainmenu/tab_multiplayer.lua +++ b/builtin/mainmenu/tab_multiplayer.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -17,259 +17,309 @@ -------------------------------------------------------------------------------- local function get_formspec(tabview, name, tabdata) -if not tabdata then tabdata = {} end - local render_details = core.is_yes(core.setting_getbool("public_serverlist")) + local retval = + "size[16,11]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + "bgcolor[#00000070;true]".. - local retval = - "label[7.75,-0.15;" .. fgettext("Address / Port :") .. "]" .. - "label[7.75,1.05;" .. fgettext("Name / Password :") .. "]" .. - "field[8,0.75;3.4,0.5;te_address;;" .. - core.formspec_escape(core.setting_get("address")) .. "]" .. - "field[11.25,0.75;1.3,0.5;te_port;;" .. - core.formspec_escape(core.setting_get("remote_port")) .. "]" .. - "checkbox[0,4.85;cb_public_serverlist;" .. fgettext("Public Serverlist") .. ";" .. - dump(core.setting_getbool("public_serverlist")) .. "]" + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;cancel;".. fgettext("Cancel") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + --"label[0,1.25;" .. fgettext("Address/Port") .. "]" .. + "field[1000.25,5.25;5.5,0.5;te_address;;" .. + core.formspec_escape(core.setting_get("address")) .. "]" .. + "field[1005.75,5.25;2.25,0.5;te_port;;" .. + core.formspec_escape(core.setting_get("remote_port")) .. "]" .. + "checkbox[1000,3.6;cb_public_serverlist;" .. fgettext("Public Serverlist") .. ";" .. + dump(core.setting_getbool("public_serverlist")) .. "]".. - if not core.setting_getbool("public_serverlist") then - retval = retval .. - "image_button[8,4.9;2,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_delete_favorite;" .. fgettext("Delete") .. "]" - end + "label[7,1.5;" .. fgettext("Select Server:") .. "]" .. + "label[0,0.25;Address: "..core.formspec_escape(core.setting_get("address")) .. "]" .. + "label[0,0.75;Port: "..core.formspec_escape(core.setting_get("remote_port")) .. "]" - retval = retval .. - "image_button[10,4.9;2,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mp_connect;" .. fgettext("Connect") .. "]" .. - "field[8,1.95;2.95,0.5;te_name;;" .. - core.formspec_escape(core.setting_get("name")) .. "]" .. - "pwdfield[10.78,1.95;1.77,0.5;te_pwd;]" .. - "box[7.73,2.35;4.3,2.28;#999999]" .. - "textarea[8.1,2.4;4.26,2.6;;" - if tabdata.fav_selected ~= nil and - menudata.favorites[tabdata.fav_selected] ~= nil and - menudata.favorites[tabdata.fav_selected].description ~= nil then - retval = retval .. - core.formspec_escape(menudata.favorites[tabdata.fav_selected].description,true) - end + --if not core.setting_getbool("public_serverlist") then + if (core.get_table_index("favourites") or 10000) <= #core.get_favorites("local") then + retval = retval .. + "image_button[4,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_delete_favorite;" .. fgettext("Delete") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + else + retval = retval .. + "image_button[4,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;add_server;" .. fgettext("Add") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + end - retval = retval .. - ";]" + retval = retval .. + "image_button[8,9.55;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mp_connect;" .. fgettext("Connect") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[3.2,9.55;0.8,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."server_flags_favourite.png;btn_mp_favour;;true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. - --favourites - if render_details then - retval = retval .. "tablecolumns[" .. - "color,span=3;" .. - "text,align=right;" .. -- clients - "text,align=center,padding=0.25;" .. -- "/" - "text,align=right,padding=0.25;" .. -- clients_max - image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" .. - image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. - image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. - "color,span=1;" .. - "text,padding=1]" -- name - else - retval = retval .. "tablecolumns[text]" - end - retval = retval .. - "table[-0.15,-0.1;7.75,5;favourites;" + "label[8,8;" .. fgettext("Name") .. ":]" .. + "field[8.3,9;3.95,0.8;te_name;;" .. + core.formspec_escape(core.setting_get("name")) .. "]" .. + "label[12,8;" .. fgettext("Password") .. ":]" .. + "pwdfield[12.3,9;4,0.8;te_pwd;]" .. + "textarea[9.3,0;2.5,3.0;;" - 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 and + menudata.favorites[tabdata.fav_selected] ~= nil and + menudata.favorites[tabdata.fav_selected].description ~= nil then + retval = retval .. + core.formspec_escape(menudata.favorites[tabdata.fav_selected].description,true) + end - if tabdata.fav_selected ~= nil then - retval = retval .. ";" .. tabdata.fav_selected .. "]" - else - retval = retval .. ";0]" - end + retval = retval .. + ";]" - return 'size[12,5.4;false]'..retval + --favourites + local function image_column(tooltip, flagname) + local ret = "image," .. + "tooltip=" .. core.formspec_escape(tooltip) .. "," + if flagname ~= 'favourite' then + ret = ret .. "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," + else + ret = ret .. "0=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. "_off.png") .. "," + end + ret = ret .. "1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png") + return ret + end + retval = retval .. "tablecolumns[" .. + "color,span=3;" .. + "text,align=right;" .. -- clients + "text,align=center,padding=0.25;" .. -- "/" + "text,align=right,padding=0.25;" .. -- clients_max + image_column("Creative mode", "creative") .. ",padding=1;" .. + image_column("Damage enabled", "damage") .. ",padding=0.25;" .. + image_column("PvP enabled", "pvp") .. ",padding=0.25;" .. + "text,padding=1]"--.. + --image_column("Favourite", "favourite") .. ",align=right]" + + retval = retval .. + "tableoptions[background=#00000000;border=false]".. + "table[0,2.2;16,6.25;favourites;" + + if #menudata.favorites == 0 then + asyncOnlineFavourites() + end + + if #menudata.favorites > 0 then + retval = retval .. render_favorite(menudata.favorites[1]) + + for i=2,#menudata.favorites,1 do + retval = retval .. "," .. render_favorite(menudata.favorites[i]) + end + end + + if tabdata.fav_selected ~= nil then + retval = retval .. ";" .. tabdata.fav_selected .. "]" + else + retval = retval .. ";0]" + end +--print(retval) + return retval end -------------------------------------------------------------------------------- local function main_button_handler(tabview, fields, name, tabdata) -if not tabdata then tabdata = {} end - if fields["te_name"] ~= nil then - gamedata.playername = fields["te_name"] - core.setting_set("name", fields["te_name"]) - end + if not tabdata then tabdata = {} end - if fields["favourites"] ~= nil then - local event = core.explode_table_event(fields["favourites"]) - if event.type == "DCL" then - if event.row <= #menudata.favorites then - if not is_server_protocol_compat_or_error(menudata.favorites[event.row].proto_min, - menudata.favorites[event.row].proto_max) then - return true - end - gamedata.address = menudata.favorites[event.row].address - gamedata.port = menudata.favorites[event.row].port - gamedata.playername = fields["te_name"] - if fields["te_pwd"] ~= nil then - gamedata.password = fields["te_pwd"] - end - gamedata.selected_world = 0 + if fields["add_server"] ~= nil then + local add_server_dlg = create_add_server_dlg(true) + add_server_dlg:set_parent(tabview) + add_server_dlg:show() + tabview:hide() + return true + end - if menudata.favorites ~= nil then - gamedata.servername = menudata.favorites[event.row].name - gamedata.serverdescription = menudata.favorites[event.row].description - end + if fields["te_name"] ~= nil then + gamedata.playername = fields["te_name"] + core.setting_set("name", fields["te_name"]) + 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 fields["favourites"] ~= nil then + local event = core.explode_table_event(fields["favourites"]) + if event.type == "DCL" then + if event.row <= #menudata.favorites then + gamedata.address = menudata.favorites[event.row].address + gamedata.port = menudata.favorites[event.row].port + gamedata.playername = fields["te_name"] + if fields["te_pwd"] ~= nil then + gamedata.password = fields["te_pwd"] + end + gamedata.selected_world = 0 - if event.type == "CHG" then - if event.row <= #menudata.favorites then - local address = menudata.favorites[event.row].address - local port = menudata.favorites[event.row].port + if menudata.favorites ~= nil then + gamedata.servername = menudata.favorites[event.row].name + gamedata.serverdescription = menudata.favorites[event.row].description + end - if address ~= nil and - port ~= nil then - core.setting_set("address",address) - core.setting_set("remote_port",port) - 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 - tabdata.fav_selected = event.row - end + if event.type == "CHG" then + if event.row <= #menudata.favorites then + local address = menudata.favorites[event.row].address + local port = menudata.favorites[event.row].port - return true - end - end + if address ~= nil and + port ~= nil then + core.setting_set("address",address) + core.setting_set("remote_port",port) + end - if fields["key_up"] ~= nil or - fields["key_down"] ~= nil then + tabdata.fav_selected = event.row + end + return true + end + end - local fav_idx = core.get_table_index("favourites") + if fields["key_up"] ~= nil or + fields["key_down"] ~= nil then - 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 fav_idx = core.get_table_index("favourites") - if menudata.favorites == nil or - menudata.favorites[fav_idx] == nil then - tabdata.fav_selected = 0 - return true - end + 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 menudata.favorites == nil or + menudata.favorites[fav_idx] == nil then + tabdata.fav_selected = 0 + return true + end - if address ~= nil and - port ~= nil then - core.setting_set("address",address) - core.setting_set("remote_port",port) - end + local address = menudata.favorites[fav_idx].address + local port = menudata.favorites[fav_idx].port - tabdata.fav_selected = fav_idx - return true - end + if address ~= nil and + port ~= nil then + core.setting_set("address",address) + core.setting_set("remote_port",port) + end - if fields["cb_public_serverlist"] ~= nil then - core.setting_set("public_serverlist", fields["cb_public_serverlist"]) + tabdata.fav_selected = fav_idx + return true + end - 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["cb_public_serverlist"] ~= nil then + core.setting_set("public_serverlist", fields["cb_public_serverlist"]) + asyncOnlineFavourites() + tabdata.fav_selected = nil + return true + end - if fields["btn_delete_favorite"] ~= nil then - local current_favourite = core.get_table_index("favourites") - if current_favourite == nil then return end - core.delete_favorite(current_favourite) - menudata.favorites = order_favorite_list(core.get_favorites()) - tabdata.fav_selected = nil + if fields["btn_mp_favour"] ~= nil then + local current_favourite = core.get_table_index("favourites") + local path = core.get_modpath('')..'/../client/'..core.formspec_escape(core.setting_get("serverlist_file")) + local favourites + if path then + local input,err,errcode = io.open(path, "r") + if input then + favourites = input:read("*all") + io.close(input) + --else + --gamedata.errormessage = err..' ('..errcode..')' + end + if favourites then + favourites = minetest.parse_json(favourites) + else + favourites = {["list"]={},} + end + table.insert(favourites.list,{ + ["address"] = fields["te_address"], + ["description"] = "Saved at ".. os.date(), + ["name"] = fields["te_address"], + ["playername"] = fields["te_name"], + ["playerpassword"] = fields["te_pwd"], + ["port"] = fields["te_port"], + } + ) - core.setting_set("address","") - core.setting_set("remote_port","30000") + favourites = minetest.write_json(favourites) - return true - end + local output,err,errcode = io.open(path, "w") + if output then + output:write(favourites or '') + io.close(output) + else + --gamedata.errormessage = fgettext("Can't write to serverlist_file! ("..path..')') + gamedata.errormessage = err..' ('..errcode..')' + end + end + asyncOnlineFavourites() + end - if (fields["btn_mp_connect"] ~= nil or - fields["key_enter"] ~= nil) and fields["te_address"] ~= nil and - fields["te_port"] ~= nil then + if fields["btn_delete_favorite"] ~= nil then + local current_favourite = core.get_table_index("favourites") + if current_favourite == nil then return end + if current_favourite > #core.get_favorites('offline') then return end + core.delete_favorite(current_favourite) + tabdata.fav_selected = nil + asyncOnlineFavourites() - 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_table_index("favourites") + core.setting_set("address","") + core.setting_set("remote_port","30000") - 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 + return true + end - gamedata.servername = menudata.favorites[fav_idx].name - gamedata.serverdescription = menudata.favorites[fav_idx].description + if fields["btn_mp_connect"] ~= nil or + fields["key_enter"] ~= nil then - if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min, - menudata.favorites[fav_idx].proto_max)then - return true - end - else - gamedata.servername = "" - gamedata.serverdescription = "" - end + gamedata.playername = fields["te_name"] + gamedata.password = fields["te_pwd"] + gamedata.address = fields["te_address"] + gamedata.port = fields["te_port"] - gamedata.selected_world = 0 + local fav_idx = core.get_table_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 + else + gamedata.servername = "" + gamedata.serverdescription = "" + end - core.setting_set("address", fields["te_address"]) - core.setting_set("remote_port",fields["te_port"]) + gamedata.selected_world = 0 - core.start() - return true - end - return false + core.setting_set("address", fields["te_address"]) + core.setting_set("remote_port",fields["te_port"]) + + core.start() + return true + end + + if fields["cancel"] ~= nil then + tabview:hide() + tabview.parent:show() + 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 - if type == "MenuQuit" then - return true - end + if type == "LEAVE" then + return + end end -------------------------------------------------------------------------------- tab_multiplayer = { - name = "multiplayer", - caption = fgettext("Client"), - cbf_formspec = get_formspec, - cbf_button_handler = main_button_handler, - --on_change = on_change - } - -function create_tab_multiplayer() - local retval = dialog_create("multiplayer", - get_formspec, - main_button_handler - --on_change - ) - return retval -end \ No newline at end of file + 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 index 6083c8d0c..43ee62905 100644 --- a/builtin/mainmenu/tab_server.lua +++ b/builtin/mainmenu/tab_server.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -18,224 +18,187 @@ -------------------------------------------------------------------------------- local function get_formspec(tabview, name, tabdata) - local index = menudata.worldlist:get_current_index( - tonumber(core.setting_get("mainmenu_last_selected_world")) - ) + local index = menudata.worldlist:get_current_index( + tonumber(core.setting_get("mainmenu_last_selected_world")) + ) - local retval = - "image_button[4,4.15;2.6,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete;" .. fgettext("Delete") .. "]" .. - "image_button[6.5,4.15;2.8,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create;" .. fgettext("New") .. "]" .. - "image_button[9.2,4.15;2.55,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_configure;" .. fgettext("Configure") .. "]" .. - "image_button[8.5,4.95;3.25,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;start_server;" .. fgettext("Start Game") .. "]" .. - "label[4,-0.25;" .. fgettext("Select World:") .. "]" .. - "checkbox[0.25,0.15;cb_creative_mode;" .. fgettext("Creative Mode") .. ";" .. - dump(core.setting_getbool("creative_mode")) .. "]" .. - "checkbox[0.25,0.6;cb_enable_damage;" .. fgettext("Enable Damage") .. ";" .. - dump(core.setting_getbool("enable_damage")) .. "]" .. - "image[0.25,1.3;0.58,0.55;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_checkf.png]".. - "image[0.25,1.3;0.58,0.55;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_check.png]".. - "image_button[0.8,1.3;3,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_trans.png;btn_single;Local Server;false;false]".. - "checkbox[0.25,1.6;cb_server_announce;" .. fgettext("Public") .. ";" .. - dump(core.setting_getbool("server_announce")) .. "]" .. - "label[0.25,2.2;" .. fgettext("Name/Password") .. "]" .. - "field[0.55,3.2;3.5,0.5;te_playername;;" .. - core.formspec_escape(core.setting_get("name")) .. "]" .. - "pwdfield[0.55,4;3.5,0.5;te_passwd;]" + local retval = + "size[16,11]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + "bgcolor[#00000070;true]".. + "image_button[4,8.7;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;start_server;".. fgettext("Play") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[7.8,8.7;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create;".. fgettext("New") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. - local bind_addr = core.setting_get("bind_address") - if bind_addr ~= nil and bind_addr ~= "" then - retval = retval .. - "field[0.55,5.2;2.25,0.5;te_serveraddr;" .. fgettext("Bind Address") .. ";" .. - core.formspec_escape(core.setting_get("bind_address")) .. "]" .. - "field[2.8,5.2;1.25,0.5;te_serverport;" .. fgettext("Port") .. ";" .. - core.formspec_escape(core.setting_get("port")) .. "]" - else - retval = retval .. - "field[0.55,5.2;3.5,0.5;te_serverport;" .. fgettext("Server Port") .. ";" .. - core.formspec_escape(core.setting_get("port")) .. "]" - end + "image_button[4,9.55;2.68,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete;".. fgettext("Delete") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[6.53,9.55;2.68,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_configure;".. fgettext("Configure") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[9.07,9.55;2.68,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;cancel;".. fgettext("Cancel") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "label[7,1.5;" .. fgettext("Select World:") .. "]" .. - retval = retval .. - "textlist[4,0.25;7.5,3.7;srv_worlds;" .. - menu_render_worldlist() .. - ";" .. index .. "]" + "checkbox[12,8.70;cb_creative_mode;" .. fgettext("Creative Mode") .. ";" .. dump(core.setting_getbool("creative_mode")) .. "]" .. + --"checkbox[1000,9.20;cb_enable_damage;" .. fgettext("Enable Damage") .. ";" .. dump(core.setting_getbool("enable_damage")) .. "]" .. + "checkbox[12,9.50;cb_server_announce;" .. fgettext("Public") .. ";" .. dump(core.setting_getbool("server_announce")) .. "]" .. + "label[0.2,8.55;" .. fgettext("Name/Password") .. "]" .. + "field[0.5,9.45;3.5,0.5;te_playername;;" - return 'size[12,5.4;false]'..retval + local nm = core.formspec_escape(core.setting_get("name")) + if nm=='' then + nm='Wanderer' + end + retval = retval .. + nm .. "]" .. + "pwdfield[0.5,10.15;3.5,0.5;te_passwd;]" + + local bind_addr = core.setting_get("bind_address") + + if not PLATFORM=="android" and bind_addr ~= nil and bind_addr ~= "" then + retval = retval .. + "field[300,0;2.25,0.5;te_serveraddr;" .. fgettext("Bind Address") .. ";" .. + core.formspec_escape(core.setting_get("bind_address")) .. "]".. + "field[300,1;1.25,0.5;te_serverport;" .. fgettext("Port") .. ";" .. + core.formspec_escape(core.setting_get("port")) .. "]" + else + retval = retval .. + "field[300,1;3.5,0.5;te_serverport;" .. fgettext("Server Port") .. ";" .. + core.formspec_escape(core.setting_get("port")) .. "]" + end + + retval = retval .. + "textlist[0,2.2;16,6.5;srv_worlds;" .. + menu_render_worldlist() .. + ";" .. (index or 1) .. ";true]" + + return retval end -------------------------------------------------------------------------------- local function main_button_handler(this, fields, name, tabdata) - local world_doubleclick = false + local world_doubleclick = false - if fields["btn_single"]~=nil then - local single = create_tab_single(true) - single:set_parent(this.parent) - single:show() - this:hide() - return true - end + if fields["srv_worlds"] ~= nil then + local event = core.explode_textlist_event(fields["srv_worlds"]) - 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"))) + return true + end + end - local selected = core.get_textlist_index("srv_worlds") - if selected ~= nil then - local filename = menudata.worldlist:get_list()[selected].path - local worldconfig = modmgr.get_worldconfig(filename) - filename = filename .. DIR_DELIM .. "world.mt" + if menu_handle_key_up_down(fields,"srv_worlds","mainmenu_last_selected_world") then + return true + end - if worldconfig.creative_mode ~= nil then - core.setting_set("creative_mode", worldconfig.creative_mode) - else - local worldfile = Settings(filename) - worldfile:set("creative_mode", core.setting_get("creative_mode")) - if not worldfile:write() then - core.log("error", "Failed to write world config file") - end - end - if worldconfig.enable_damage ~= nil then - core.setting_set("enable_damage", worldconfig.enable_damage) - else - local worldfile = Settings(filename) - worldfile:set("enable_damage", core.setting_get("enable_damage")) - if not worldfile:write() then - core.log("error", "Failed to write world config file") - end - end - end + if fields["cb_creative_mode"] then + core.setting_set("creative_mode", fields["cb_creative_mode"]) + local bool = fields["cb_creative_mode"] + if bool == 'true' then + bool = 'false' + else + bool = 'true' + end + core.setting_set("enable_damage", bool) + print(bool) + return true + end - 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"))) - return true - end - end + if fields["cb_enable_damage"] then + core.setting_set("enable_damage", fields["cb_enable_damage"]) + return true + end - if menu_handle_key_up_down(fields,"srv_worlds","mainmenu_last_selected_world") then - return true - end + if fields["cb_server_announce"] then + core.setting_set("server_announce", fields["cb_server_announce"]) + return true + end - if fields["cb_creative_mode"] then - core.setting_set("creative_mode", fields["cb_creative_mode"]) - local selected = core.get_textlist_index("srv_worlds") - local filename = menudata.worldlist:get_list()[selected].path .. - DIR_DELIM .. "world.mt" + 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) - local worldfile = Settings(filename) - worldfile:set("creative_mode", fields["cb_creative_mode"]) - if not worldfile:write() then - core.log("error", "Failed to write world config file") - end - return true - end + core.setting_set("port",gamedata.port) + if fields["te_serveraddr"] ~= nil then + core.setting_set("bind_address",fields["te_serveraddr"]) + end - if fields["cb_enable_damage"] then - core.setting_set("enable_damage", fields["cb_enable_damage"]) - local selected = core.get_textlist_index("srv_worlds") - local filename = menudata.worldlist:get_list()[selected].path .. - DIR_DELIM .. "world.mt" + --update last game + local world = menudata.worldlist:get_raw_element(gamedata.selected_world) - local worldfile = Settings(filename) - worldfile:set("enable_damage", fields["cb_enable_damage"]) - if not worldfile:write() then - core.log("error", "Failed to write world config file") - end - return true - end + local game,index = gamemgr.find_by_gameid(world.gameid) + core.setting_set("menu_last_game",game.id) + core.start() + return true + end + end - if fields["cb_server_announce"] then - core.setting_set("server_announce", fields["cb_server_announce"]) - return true - end + if fields["world_create"] ~= nil then + 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["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) + 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 - core.setting_set("port",gamedata.port) - if fields["te_serveraddr"] ~= nil then - core.setting_set("bind_address",fields["te_serveraddr"]) - end + return true + end - --update last game - local world = menudata.worldlist:get_raw_element(gamedata.selected_world) + 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)) - local game,index = gamemgr.find_by_gameid(world.gameid) - core.setting_set("menu_last_game",game.id) - core.start() - return true - end - end + if (configdialog ~= nil) then + configdialog:set_parent(this) + configdialog:show() + this:hide() + end + end + return true + end - if fields["world_create"] ~= nil then - 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["cancel"] ~= nil then + this:hide() + this.parent:show() + 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 + return false end -------------------------------------------------------------------------------- tab_server = { - name = "server", - caption = fgettext("Server"), - cbf_formspec = get_formspec, - cbf_button_handler = main_button_handler, - on_change = nil - } - -function create_tab_server() - local retval = dialog_create("server", - get_formspec, - main_button_handler, - nil) - return retval -end \ No newline at end of file + 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 index ed51c2007..9b80b58d2 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify @@ -16,368 +16,450 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- - local dd_filter_labels = { - fgettext("No Filter"), - fgettext("Bilinear Filter"), - fgettext("Trilinear Filter") + fgettext("No Filter"), + fgettext("Bilinear Filter"), + fgettext("Trilinear Filter") } local filters = { - {dd_filter_labels[1]..","..dd_filter_labels[2]..","..dd_filter_labels[3]}, - {"", "bilinear_filter", "trilinear_filter"}, + {dd_filter_labels[1]..","..dd_filter_labels[2]..","..dd_filter_labels[3]}, + {"", "bilinear_filter", "trilinear_filter"}, } local dd_mipmap_labels = { - fgettext("No Mipmap"), - fgettext("Mipmap"), - fgettext("Mipmap + Aniso. Filter") + fgettext("No Mipmap"), + fgettext("Mipmap"), + fgettext("Mipmap + Aniso. Filter") } local mipmap = { - {dd_mipmap_labels[1]..","..dd_mipmap_labels[2]..","..dd_mipmap_labels[3]}, - {"", "mip_map", "anisotropic_filter"}, + {dd_mipmap_labels[1]..","..dd_mipmap_labels[2]..","..dd_mipmap_labels[3]}, + {"", "mip_map", "anisotropic_filter"}, } local function getFilterSettingIndex() - if (core.setting_get(filters[2][3]) == "true") then - return 3 - end - if (core.setting_get(filters[2][3]) == "false" and core.setting_get(filters[2][2]) == "true") then - return 2 - end - return 1 + if (core.setting_get(filters[2][3]) == "true") then + return 3 + end + if (core.setting_get(filters[2][3]) == "false" and core.setting_get(filters[2][2]) == "true") then + return 2 + end + return 1 end local function getMipmapSettingIndex() - if (core.setting_get(mipmap[2][3]) == "true") then - return 3 - end - if (core.setting_get(mipmap[2][3]) == "false" and core.setting_get(mipmap[2][2]) == "true") then - return 2 - end - return 1 + if (core.setting_get(mipmap[2][3]) == "true") then + return 3 + end + if (core.setting_get(mipmap[2][3]) == "false" and core.setting_get(mipmap[2][2]) == "true") then + return 2 + end + return 1 end local function video_driver_fname_to_name(selected_driver) - local video_drivers = core.get_video_drivers() + local video_drivers = core.get_video_drivers() - for i=1, #video_drivers do - if selected_driver == video_drivers[i].friendly_name then - return video_drivers[i].name:lower() - end - end + for i=1, #video_drivers do + if selected_driver == video_drivers[i].friendly_name then + return video_drivers[i].name:lower() + end + end - return "" + return "" end - local function dlg_confirm_reset_formspec(data) - local retval = - "size[8,3]" .. - "label[1,1;".. fgettext("Are you sure to reset your singleplayer world?") .. "]".. - "image_button[1,2;2.6,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_reset_singleplayer_confirm;".. - fgettext("Yes") .. "]" .. - "image_button[4,2;2.8,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_reset_singleplayer_cancel;".. - fgettext("No!!!") .. "]" - return retval + local retval = + "size[8,3]" .. + "label[1,1;".. fgettext("Are you sure to reset your singleplayer world?") .. "]".. + "image_button[1,2;2.6,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_reset_singleplayer_confirm;".. + fgettext("Yes") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[4,2;2.8,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;dlg_reset_singleplayer_cancel;".. + fgettext("No!!!") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + 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 + 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 + 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 + if found_singleplayerworld then + core.delete_world(gamedata.worldindex) + end - core.create_world("singleplayerworld", 1) + core.create_world("singleplayerworld", 1) - worldlist = core.get_worlds() + worldlist = core.get_worlds() - found_singleplayerworld = false + found_singleplayerworld = false - for i=1,#worldlist,1 do - if worldlist[i].name == "singleplayerworld" then - found_singleplayerworld = true - gamedata.worldindex = i - end - end - end + 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() - return true + this.parent:show() + this:hide() + this:delete() + return true end local function showconfirm_reset(tabview) - local new_dlg = dialog_create("reset_spworld", - dlg_confirm_reset_formspec, - dlg_confirm_reset_btnhandler, - nil) - new_dlg:set_parent(tabview) - tabview:hide() - new_dlg:show() + local new_dlg = dialog_create("reset_spworld", + dlg_confirm_reset_formspec, + dlg_confirm_reset_btnhandler, + nil) + new_dlg:set_parent(tabview) + tabview:hide() + new_dlg:show() end local function gui_scale_to_scrollbar() - local current_value = tonumber(core.setting_get("gui_scaling")) - if (current_value == nil) or current_value < 0.25 then - return 0 - end - if current_value <= 1.25 then - return ((current_value - 0.25)/ 1.0) * 700 - end - if current_value <= 6 then - return ((current_value -1.25) * 100) + 700 - end + local current_value = tonumber(core.setting_get("gui_scaling")) - return 1000 + if (current_value == nil) or current_value < 0.25 then + return 0 + end + + if current_value <= 1.25 then + return ((current_value - 0.25)/ 1.0) * 700 + end + + if current_value <= 6 then + return ((current_value -1.25) * 100) + 700 + end + + return 1000 end local function scrollbar_to_gui_scale(value) - value = tonumber(value) - if (value <= 700) then - return ((value / 700) * 1.0) + 0.25 - end - if (value <=1000) then - return ((value - 700) / 100) + 1.25 - end + value = tonumber(value) - return 1 + if (value <= 700) then + return ((value / 700) * 1.0) + 0.25 + end + + if (value <=1000) then + return ((value - 700) / 100) + 1.25 + end + + return 1 end local function formspec(tabview, name, tabdata) - local video_drivers = core.get_video_drivers() - local current_video_driver = core.setting_get("video_driver"):lower() + local video_drivers = core.get_video_drivers() + local current_video_driver = core.setting_get("video_driver"):lower() - local driver_formspec_string = "" - local driver_current_idx = 0 + local driver_formspec_string = "" + local driver_current_idx = 0 - for i=2, #video_drivers do - driver_formspec_string = driver_formspec_string .. video_drivers[i].friendly_name - if i ~= #video_drivers then - driver_formspec_string = driver_formspec_string .. "," - end + for i=2, #video_drivers do + driver_formspec_string = driver_formspec_string .. video_drivers[i].friendly_name + if i ~= #video_drivers then + driver_formspec_string = driver_formspec_string .. "," + end - if current_video_driver == video_drivers[i].name:lower() then - driver_current_idx = i - 1 - end - end + if current_video_driver == video_drivers[i].name:lower() then + driver_current_idx = i - 1 + end + end - local tab_string = - "box[0,0;3.5,3.9;#999999]" .. - "checkbox[0.25,0;cb_smooth_lighting;".. fgettext("Smooth Lighting") - .. ";".. dump(core.setting_getbool("smooth_lighting")) .. "]".. - "checkbox[0.25,0.5;cb_particles;".. fgettext("Enable Particles") .. ";" - .. dump(core.setting_getbool("enable_particles")) .. "]".. - "checkbox[0.25,1;cb_3d_clouds;".. fgettext("3D Clouds") .. ";" - .. dump(core.setting_getbool("enable_3d_clouds")) .. "]".. - "checkbox[0.25,1.5;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";" - .. dump(core.setting_getbool("new_style_leaves")) .. "]".. - "checkbox[0.25,2.0;cb_opaque_water;".. fgettext("Opaque Water") .. ";" - .. dump(core.setting_getbool("opaque_water")) .. "]".. - "checkbox[0.25,2.5;cb_connected_glass;".. fgettext("Connected Glass") .. ";" - .. dump(core.setting_getbool("connected_glass")) .. "]".. - "checkbox[0.25,3.0;cb_node_highlighting;".. fgettext("Node Highlighting") .. ";" - .. dump(core.setting_getbool("enable_node_highlighting")) .. "]".. - "box[3.75,0;3.75,3.45;#999999]" .. - "label[3.85,0.1;".. fgettext("Texturing:") .. "]".. - "dropdown[3.85,0.55;3.85;dd_filters;" .. filters[1][1] .. ";" - .. getFilterSettingIndex() .. "]" .. - "dropdown[3.85,1.35;3.85;dd_mipmap;" .. mipmap[1][1] .. ";" - .. getMipmapSettingIndex() .. "]" .. - "label[3.85,2.15;".. fgettext("Rendering:") .. "]".. - "dropdown[3.85,2.6;3.85;dd_video_driver;" - .. driver_formspec_string .. ";" .. driver_current_idx .. "]" .. - "tooltip[dd_video_driver;" .. - fgettext("Restart MultiCraft for driver change to take effect") .. "]" - if PLATFORM ~= "Android" then - tab_string = tab_string .. - "image_button[8,4.75;3.75,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_change_keys;".. fgettext("Change keys") .. "]" - else - tab_string = tab_string .. - "image_button[3.75,5.5;3.95,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_reset_singleplayer;".. fgettext("Reset singleplayer world") .. "]" - end - tab_string = tab_string .. - "box[0,4.25;3.5,1.1;#999999]" .. - "label[0.25,4.25;" .. fgettext("GUI scale factor") .. "]" .. - "scrollbar[0.25,4.75;3,0.4;sb_gui_scaling;horizontal;" .. - gui_scale_to_scrollbar() .. "]" .. - "tooltip[sb_gui_scaling;" .. - fgettext("Scaling factor applied to menu elements: ") .. - dump(core.setting_get("gui_scaling")) .. "]" + local tab_string = + "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. - if PLATFORM == "Android" then - tab_string = tab_string .. - "box[3.75,3.55;3.75,1.8;#999999]" .. - "checkbox[3.9,3.45;cb_touchscreen_target;".. fgettext("Touch free target") .. ";" - .. dump(core.setting_getbool("touchtarget")) .. "]" - end + "box[0.75,2.5;4.5,3.9;#999999]" .. + "checkbox[1.0,2.5;cb_smooth_lighting;".. fgettext("Smooth Lighting") + .. ";".. dump(core.setting_getbool("smooth_lighting")) .. "]".. + "checkbox[1.0,3.0;cb_particles;".. fgettext("Enable Particles") .. ";" + .. dump(core.setting_getbool("enable_particles")) .. "]".. + "checkbox[1.0,3.5;cb_3d_clouds;".. fgettext("3D Clouds") .. ";" + .. dump(core.setting_getbool("enable_3d_clouds")) .. "]".. + "checkbox[1.0,4.0;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";" + .. dump(core.setting_getbool("new_style_leaves")) .. "]".. + "checkbox[1.0,4.5;cb_opaque_water;".. fgettext("Opaque Water") .. ";" + .. dump(core.setting_getbool("opaque_water")) .. "]".. + "checkbox[1.0,5.0;cb_connected_glass;".. fgettext("Connected Glass") .. ";" + .. dump(core.setting_getbool("connected_glass")) .. "]".. + "checkbox[1.0,5.5;cb_node_highlighting;".. fgettext("Node Highlighting") .. ";" + .. dump(core.setting_getbool("enable_node_highlighting")) .. "]".. - if core.setting_get("touchscreen_threshold") ~= nil then - tab_string = tab_string .. - "label[4.3,4.1;" .. fgettext("Touchthreshold (px)") .. "]" .. - "dropdown[3.85,4.55;3.85;dd_touchthreshold;0,10,20,30,40,50;" .. - ((tonumber(core.setting_get("touchscreen_threshold"))/10)+1) .. "]" - end - return 'size[7.70,6.2,false]'..tab_string + "box[5.5,2.5;4,3.45;#999999]" .. + "label[5.85,2.5;".. fgettext("Texturing:") .. "]".. + "dropdown[5.85,3.05;3.85;dd_filters;" .. filters[1][1] .. ";" + .. getFilterSettingIndex() .. "]" .. + "dropdown[5.85,3.85;3.85;dd_mipmap;" .. mipmap[1][1] .. ";" + .. getMipmapSettingIndex() .. "]" .. + "label[5.85,4.65;".. fgettext("Rendering:") .. "]".. + "dropdown[5.85,5.1;3.85;dd_video_driver;" + .. driver_formspec_string .. ";" .. driver_current_idx .. "]" .. + "tooltip[dd_video_driver;" .. + fgettext("Restart minetest for driver change to take effect") .. "]" + + + + + if PLATFORM ~= "Android" then + tab_string = tab_string .. + "box[9.75,2.5;5.25,4;#999999]".. + "checkbox[10,2.5;cb_shaders;".. fgettext("Shaders") .. ";" + .. dump(core.setting_getbool("enable_shaders")) .. "]".. + "image_button[0,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_change_keys;".. fgettext("Change keys") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]"--.. +-- "image_button[3.75,5;3.88,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_reset_singleplayer;".. fgettext("Reset singleplayer world") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + else + --tab_string = tab_string .. +-- "image_button[3.75,5;3.88,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_reset_singleplayer;".. fgettext("Reset singleplayer world") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + end + + tab_string = tab_string .. + "image_button[4,9.55;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_textures;".. fgettext("Texturepacks") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).. + "menu_button_b.png]".. + "image_button[8,9.55;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_show_credits;".. fgettext("Credits") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_cancel;".. fgettext("OK") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]" + + + if PLATFORM == "Android" then + tab_string = tab_string .. + "box[9.75,2.5;5.25,2.5;#999999]" .. + "checkbox[10,2.75;cb_touchscreen_target;".. fgettext("Touch free target") .. ";" .. dump(core.setting_getbool("touchtarget")) .. "]".. + + "box[0.75,6.8;14.25,1.35;#999999]" .. + "label[1.5,6.8;" .. fgettext("GUI scale factor") .. "]".. + "scrollbar[1.0,7.2;13.75,0.7;sb_gui_scaling;horizontal;" .. gui_scale_to_scrollbar() .. "]" .. + "tooltip[sb_gui_scaling;" .. fgettext("Scaling factor applied to menu elements: ") .. dump(core.setting_get("gui_scaling")) .. "]" + + -- if core.setting_get("touchscreen_threshold") ~= nil then + tab_string = tab_string .. + "label[10,3.5;" .. fgettext("Touchthreshold (px)") .. "]" .. + "dropdown[10,4.0;5.18;dd_touchthreshold;0,10,20,30,40,50;" .. ((tonumber(core.setting_get("touchscreen_threshold") or 20)/10)+1) .. "]" + -- end + + else + tab_string = tab_string .. + "box[0.75,6.8;14.25,1.35;#999999]" .. + "label[1.5,6.8;" .. fgettext("GUI scale factor") .. "]".. + "scrollbar[1.0,7.5;13.75,0.4;sb_gui_scaling;horizontal;" .. gui_scale_to_scrollbar() .. "]" .. + "tooltip[sb_gui_scaling;" .. fgettext("Scaling factor applied to menu elements: ") .. dump(core.setting_get("gui_scaling")) .. "]" + end + + if PLATFORM ~= "Android" then + if core.setting_getbool("enable_shaders") then + tab_string = tab_string .. + "checkbox[10,3.0;cb_bumpmapping;".. fgettext("Bumpmapping") .. ";" + .. dump(core.setting_getbool("enable_bumpmapping")) .. "]".. + "checkbox[10,3.5;cb_generate_normalmaps;".. fgettext("Generate Normalmaps") .. ";" + .. dump(core.setting_getbool("generate_normalmaps")) .. "]".. + "checkbox[10,4.0;cb_parallax;".. fgettext("Parallax Occlusion") .. ";" + .. dump(core.setting_getbool("enable_parallax_occlusion")) .. "]".. + "checkbox[10,4.5;cb_waving_water;".. fgettext("Waving Water") .. ";" + .. dump(core.setting_getbool("enable_waving_water")) .. "]".. + "checkbox[10,5.0;cb_waving_leaves;".. fgettext("Waving Leaves") .. ";" + .. dump(core.setting_getbool("enable_waving_leaves")) .. "]".. + "checkbox[10,5.5;cb_waving_plants;".. fgettext("Waving Plants") .. ";" + .. dump(core.setting_getbool("enable_waving_plants")) .. "]" + else + tab_string = tab_string .. + "textlist[10.3,3.2;4,1;;#888888" .. fgettext("Bumpmapping") .. ";0;true]" .. + "textlist[10.3,3.7;4,1;;#888888" .. fgettext("Generate Normalmaps") .. ";0;true]" .. + "textlist[10.3,4.2;4,1;;#888888" .. fgettext("Parallax Occlusion") .. ";0;true]" .. + "textlist[10.3,4.7;4,1;;#888888" .. fgettext("Waving Water") .. ";0;true]" .. + "textlist[10.3,5.2;4,1;;#888888" .. fgettext("Waving Leaves") .. ";0;true]" .. + "textlist[10.3,5.7;4,1;;#888888" .. fgettext("Waving Plants") .. ";0;true]" + end + 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_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_connected_glass"] then - core.setting_set("connected_glass", fields["cb_connected_glass"]) - return true - end - if fields["cb_node_highlighting"] then - core.setting_set("enable_node_highlighting", fields["cb_node_highlighting"]) - return true - end - if fields["cb_particles"] then - core.setting_set("enable_particles", fields["cb_particles"]) - return true - end - if fields["cb_bumpmapping"] then - core.setting_set("enable_bumpmapping", fields["cb_bumpmapping"]) - end - if fields["cb_generate_normalmaps"] then - core.setting_set("generate_normalmaps", fields["cb_generate_normalmaps"]) - 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_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_connected_glass"] then + core.setting_set("connected_glass", fields["cb_connected_glass"]) + return true + end + if fields["cb_particles"] then + core.setting_set("enable_particles", fields["cb_particles"]) + return true + end + if fields["cb_bumpmapping"] then + core.setting_set("enable_bumpmapping", fields["cb_bumpmapping"]) + end + if fields["cb_generate_normalmaps"] then + core.setting_set("generate_normalmaps", fields["cb_generate_normalmaps"]) + 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["sb_gui_scaling"] then - local event = core.explode_scrollbar_event(fields["sb_gui_scaling"]) + if fields["sb_gui_scaling"] then + local event = core.explode_scrollbar_event(fields["sb_gui_scaling"]) - if event.type == "CHG" then - local tosave = string.format("%.2f",scrollbar_to_gui_scale(event.value)) - core.setting_set("gui_scaling",tosave) - return true - end - end - if fields["cb_touchscreen_target"] then - core.setting_set("touchtarget", fields["cb_touchscreen_target"]) - return true - end - if fields["btn_reset_singleplayer"] then - showconfirm_reset(this) - return true - end + if event.type == "CHG" then + local tosave = string.format("%.2f",scrollbar_to_gui_scale(event.value)) + core.setting_set("gui_scaling",tosave) + return true + end + end + if fields["cb_touchscreen_target"] then + core.setting_set("touchtarget", fields["cb_touchscreen_target"]) + return true + end + if fields["btn_reset_singleplayer"] then + showconfirm_reset(this) + return true + end - --Note dropdowns have to be handled LAST! - local ddhandled = false + if fields["btn_cancel"] ~= nil then + this:hide() + this.parent:show() + return true + end - if fields["dd_touchthreshold"] then - core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"]) - ddhandled = true - end - if fields["dd_video_driver"] then - core.setting_set("video_driver", - video_driver_fname_to_name(fields["dd_video_driver"])) - ddhandled = true - end - if fields["dd_filters"] == dd_filter_labels[1] then - core.setting_set("bilinear_filter", "false") - core.setting_set("trilinear_filter", "false") - ddhandled = true - end - if fields["dd_filters"] == dd_filter_labels[2] then - core.setting_set("bilinear_filter", "true") - core.setting_set("trilinear_filter", "false") - ddhandled = true - end - if fields["dd_filters"] == dd_filter_labels[3] then - core.setting_set("bilinear_filter", "false") - core.setting_set("trilinear_filter", "true") - ddhandled = true - end - if fields["dd_mipmap"] == dd_mipmap_labels[1] then - core.setting_set("mip_map", "false") - core.setting_set("anisotropic_filter", "false") - ddhandled = true - end - if fields["dd_mipmap"] == dd_mipmap_labels[2] then - core.setting_set("mip_map", "true") - core.setting_set("anisotropic_filter", "false") - ddhandled = true - end - if fields["dd_mipmap"] == dd_mipmap_labels[3] then - core.setting_set("mip_map", "true") - core.setting_set("anisotropic_filter", "true") - ddhandled = true - end + local index = '' + if fields["btn_show_textures"] then index = "texturepacks" end + if fields["btn_show_credits"] then index = "credits" end - return ddhandled + for name,def in pairs(this.parent.tablist) do + if index == def.name then + local get_fs = function() + local retval = def.get_formspec(this.parent, name, tabdata) + retval = 'size[12,5.2]'..retval + return retval + end + local dlg = dialog_create(def.name, get_fs, def.button_handler, def.on_change) + dlg:set_parent(this) + this:hide() + dlg:show() + return dlg + end + end + + --Note dropdowns have to be handled LAST! + local ddhandled = false + + if fields["dd_touchthreshold"] then + core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"]) + ddhandled = true + end + + if fields["dd_video_driver"] then + core.setting_set("video_driver", + video_driver_fname_to_name(fields["dd_video_driver"])) + ddhandled = true + end + if fields["dd_filters"] == dd_filter_labels[1] then + core.setting_set("bilinear_filter", "false") + core.setting_set("trilinear_filter", "false") + ddhandled = true + end + if fields["dd_filters"] == dd_filter_labels[2] then + core.setting_set("bilinear_filter", "true") + core.setting_set("trilinear_filter", "false") + ddhandled = true + end + if fields["dd_filters"] == dd_filter_labels[3] then + core.setting_set("bilinear_filter", "false") + core.setting_set("trilinear_filter", "true") + ddhandled = true + end + if fields["dd_mipmap"] == dd_mipmap_labels[1] then + core.setting_set("mip_map", "false") + core.setting_set("anisotropic_filter", "false") + ddhandled = true + end + if fields["dd_mipmap"] == dd_mipmap_labels[2] then + core.setting_set("mip_map", "true") + core.setting_set("anisotropic_filter", "false") + ddhandled = true + end + if fields["dd_mipmap"] == dd_mipmap_labels[3] then + core.setting_set("mip_map", "true") + core.setting_set("anisotropic_filter", "true") + ddhandled = true + end + + return ddhandled end tab_settings = { - name = "settings", - caption = fgettext("Settings"), - cbf_formspec = formspec, - cbf_button_handler = handle_settings_buttons -} - -function create_tab_settings() - local retval = dialog_create("settings", - formspec, - handle_settings_buttons, - nil) - return retval -end + 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 index 650521c71..3a51687ad 100644 --- a/builtin/mainmenu/tab_simple_main.lua +++ b/builtin/mainmenu/tab_simple_main.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify @@ -16,190 +16,54 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- + --favourites +local function image_column(tooltip, flagname) + return "image," .. + "tooltip=" .. core.formspec_escape(tooltip) .. "," .. + "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. + "1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png") +end + local function get_formspec(tabview, name, tabdata) - local retval = "" - - local render_details = dump(core.setting_getbool("public_serverlist")) - - retval = retval .. - "label[8,0.8;".. fgettext("Name/Password") .. "]" .. - "field[0.25,3.25;5.5,0.5;te_address;;" .. - core.formspec_escape(core.setting_get("address")) .."]" .. - "field[5.75,3.25;2.25,0.5;te_port;;" .. - core.formspec_escape(core.setting_get("remote_port")) .."]" .. - "checkbox[8,-0.25;cb_public_serverlist;".. fgettext("Public Serverlist") .. ";" .. - render_details .. "]" - - retval = retval .. - "image_button[8,2.5;4,1.5;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_mp_connect;".. fgettext("Connect") .. "]" .. - "field[8.75,1.5;3.5,0.5;te_name;;" .. - core.formspec_escape(core.setting_get("name")) .."]" .. - "pwdfield[8.75,2.3;3.5,0.5;te_pwd;]" - - if render_details then - retval = retval .. "tablecolumns[" .. - "color,span=3;" .. - "text,align=right;" .. -- clients - "text,align=center,padding=0.25;" .. -- "/" - "text,align=right,padding=0.25;" .. -- clients_max - image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" .. - image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. - image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. - "color,span=1;" .. - "text,padding=1]" -- name - else - retval = retval .. "tablecolumns[text]" - end - retval = retval .. - "table[-0.05,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.28,3.75;12.4,0.1;#FFFFFF]" - - -- checkboxes - retval = retval .. - "checkbox[8.0,3.9;cb_creative;".. fgettext("Creative Mode") .. ";" .. - dump(core.setting_getbool("creative_mode")) .. "]".. - "checkbox[8.0,4.4;cb_damage;".. fgettext("Enable Damage") .. ";" .. - dump(core.setting_getbool("enable_damage")) .. "]" - -- buttons - retval = retval .. - "image_button[2.0,4.5;6,1.5;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]" .. - "image_button[8.25,4.5;2.5,1.5;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_config_sp_world;" .. fgettext("Config mods") .. "]" - - return retval + local retval = "" + retval = retval .. "bgcolor[#00000000;false]" + retval = retval .. "image_button[2.5,1.0;7,1;multicraftbutton.png;btn_show_singleplayer;".. fgettext("Singleplayer") .. ";true;true;multicraftbutton.png]" + retval = retval .. "image_button[2.5,2.4;7,1;multicraftbutton.png;btn_show_multiplayer;" .. fgettext("Multiplayer") .. ";true;true;multicraftbutton.png]" + retval = retval .. "image_button[2.5,3.8;7,1;multicraftbutton.png;btn_show_options;".. fgettext("Options") .. ";true;true;multicraftbutton.png]" + retval = retval .. "image_button[2.5,5.2;7,1;multicraftbutton.png;btn_exit;".. fgettext("Exit") .. ";true;true;multicraftbutton.png]" + return retval end -------------------------------------------------------------------------------- + local function main_button_handler(tabview, fields, name, tabdata) + local index = 0 + if fields["btn_show_singleplayer"] then index = 1 end + if fields["btn_show_multiplayer"] then index = 2 end + if fields["btn_show_options"] then index = 3 end + if fields["btn_exit"] then core.close() end - if fields["btn_start_singleplayer"] then - gamedata.selected_world = gamedata.worldindex - gamedata.singleplayer = true - core.start() - return true - end - - if fields["favourites"] ~= nil then - local event = core.explode_table_event(fields["favourites"]) - - if event.type == "CHG" then - if event.row <= #menudata.favorites then - local address = menudata.favorites[event.row].address - local port = menudata.favorites[event.row].port - - if address ~= nil and - port ~= nil then - core.setting_set("address",address) - core.setting_set("remote_port",port) - end - - tabdata.fav_selected = event.row - end - end - 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 - return true - end - - if fields["cb_creative"] then - core.setting_set("creative_mode", fields["cb_creative"]) - return true - end - - if fields["cb_damage"] then - core.setting_set("enable_damage", fields["cb_damage"]) - 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 - - if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min, - menudata.favorites[fav_idx].proto_max) then - return true - end - 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 - - if fields["btn_config_sp_world"] ~= nil then - local configdialog = create_configure_world_dlg(1) - - if (configdialog ~= nil) then - configdialog:set_parent(tabview) - tabview:hide() - configdialog:show() - end - return true - end + --switch_to_tab(self, index) 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 + if type == "LEAVE" then + return + end + core.set_topleft_text('Multicraft II') + 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 - } + 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 index 5cb7a9060..863d231b0 100644 --- a/builtin/mainmenu/tab_singleplayer.lua +++ b/builtin/mainmenu/tab_singleplayer.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -16,285 +16,224 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. local function current_game() - local last_game_id = core.setting_get("menu_last_game") - local game, index = gamemgr.find_by_gameid(last_game_id) + local last_game_id = core.setting_get("menu_last_game") + local game, index = gamemgr.find_by_gameid(last_game_id) - return game + return game end local function singleplayer_refresh_gamebar() - local old_bar = ui.find_by_name("game_button_bar") + local old_bar = ui.find_by_name("game_button_bar") - if old_bar ~= nil then - old_bar:delete() - end + 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.set_topleft_text(gamemgr.games[j].name) - 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 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.set_topleft_text(gamemgr.games[j].name) + 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}) + 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 + for i=1,#gamemgr.games,1 do + local btn_name = "game_btnbar_" .. gamemgr.games[i].id - local image = nil - local text = nil - local tooltip = core.formspec_escape(gamemgr.games[i].name) + local image = nil + local text = nil + local tooltip = core.formspec_escape(gamemgr.games[i].name) - if gamemgr.games[i].menuicon_path ~= nil and - gamemgr.games[i].menuicon_path ~= "" then - image = core.formspec_escape(gamemgr.games[i].menuicon_path) - else + 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) + 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, tooltip) - end + text = part1 .. "\n" .. part2 + if part3 ~= nil and + part3 ~= "" then + text = text .. "\n" .. part3 + end + end + btnbar:add_button(btn_name, text, image, tooltip) + end end local function get_formspec(tabview, name, tabdata) - local retval = "" + local retval = "" - local index = filterlist.get_current_index(menudata.worldlist, - tonumber(core.setting_get("mainmenu_last_selected_world")) - ) + local index = filterlist.get_current_index(menudata.worldlist, + tonumber(core.setting_get("mainmenu_last_selected_world")) + ) - retval = retval .. - "image_button[4,4.15;2.6,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete;".. fgettext("Delete") .. "]" .. - "image_button[6.5,4.15;2.8,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create;".. fgettext("New") .. "]" .. - "image_button[9.2,4.15;2.55,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_configure;".. fgettext("Configure") .. "]" .. - "image_button[8.5,4.95;3.25,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_button.png;play;".. fgettext("Play") .. "]" .. - "label[4,-0.25;".. fgettext("Select World:") .. "]".. - "checkbox[0.25,0.15;cb_creative_mode;".. fgettext("Creative Mode") .. ";" .. - dump(core.setting_getbool("creative_mode")) .. "]".. - "checkbox[0.25,0.6;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. - dump(core.setting_getbool("enable_damage")) .. "]".. - "image[0.25,1.3;0.58,0.55;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_checkf.png]".. - "image_button[0.8,1.3;3,0.8;"..multicraft.formspec_escape(mm_texture.basetexturedir).."menu_trans.png;btn_server;Local Server;false;false]".. - "textlist[4,0.25;7.5,3.7;sp_worlds;" .. - menu_render_worldlist() .. - ";" .. index .. "]" - return 'size[12,5.4;false]'..retval + retval = retval .. + "image_button[4,4.05;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;play;".. fgettext("Play") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[7.8,4.05;3.95,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_create;".. fgettext("New") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + + "image_button[4,4.8;2.68,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_delete;".. fgettext("Delete") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[6.53,4.8;2.68,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;world_configure;".. fgettext("Configure") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "image_button[9.07,4.8;2.68,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;cancel;".. fgettext("Cancel") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + + "label[4,-0.25;".. fgettext("Select World:") .. "]".. + "checkbox[0.25,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" .. + dump(core.setting_getbool("creative_mode")) .. "]".. + "checkbox[0.25,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) - name = "singleplayer" + --assert(name == "singleplayer") - local world_doubleclick = false + local world_doubleclick = false - if fields["btn_server"]~=nil then - local single = create_tab_server(true) - single:set_parent(this.parent) - single:show() - this:hide() - return true - end + if fields["sp_worlds"] ~= nil then + local event = core.explode_textlist_event(fields["sp_worlds"]) - if fields["sp_worlds"] ~= nil then - local event = core.explode_textlist_event(fields["sp_worlds"]) + if event.type == "DCL" then + world_doubleclick = true + end - local selected = core.get_textlist_index("sp_worlds") - if selected ~= nil then - local filename = menudata.worldlist:get_list()[selected].path - local worldconfig = modmgr.get_worldconfig(filename) - filename = filename .. DIR_DELIM .. "world.mt" + if event.type == "CHG" then + core.setting_set("mainmenu_last_selected_world", + menudata.worldlist:get_raw_index(core.get_textlist_index("sp_worlds"))) + return true + end + end - if worldconfig.creative_mode ~= nil then - core.setting_set("creative_mode", worldconfig.creative_mode) - else - local worldfile = Settings(filename) - worldfile:set("creative_mode", core.setting_get("creative_mode")) - if not worldfile:write() then - core.log("error", "Failed to write world config file") - end - end - if worldconfig.enable_damage ~= nil then - core.setting_set("enable_damage", worldconfig.enable_damage) - else - local worldfile = Settings(filename) - worldfile:set("enable_damage", core.setting_get("enable_damage")) - if not worldfile:write() then - core.log("error", "Failed to write world config file") - end - end - end + if menu_handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world") then + return true + end - if event.type == "DCL" then - world_doubleclick = true - end + if fields["cb_creative_mode"] then + core.setting_set("creative_mode", fields["cb_creative_mode"]) + return true + end - if event.type == "CHG" and selected ~= nil then - core.setting_set("mainmenu_last_selected_world", - menudata.worldlist:get_raw_index(selected)) - return true - end - end + if fields["cb_enable_damage"] then + core.setting_set("enable_damage", fields["cb_enable_damage"]) + return true + end - if menu_handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world") then - return true - end + if fields["play"] ~= nil or + world_doubleclick or + fields["key_enter"] then + local selected = core.get_textlist_index("sp_worlds") - if fields["cb_creative_mode"] then - core.setting_set("creative_mode", fields["cb_creative_mode"]) - local selected = core.get_textlist_index("sp_worlds") - if selected then - local filename = menudata.worldlist:get_list()[selected].path .. - DIR_DELIM .. "world.mt" + if selected ~= nil then + gamedata.selected_world = menudata.worldlist:get_raw_index(selected) + gamedata.singleplayer = true - local test = io.open(filename) - if test then - io.close(test) - local worldfile = Settings(filename) - worldfile:set("creative_mode", fields["cb_creative_mode"]) - -- if not worldfile:write() then - -- core.log("error", "Failed to write world config file") - -- end - end - end - return true - end + core.start() + end + return true + end - if fields["cb_enable_damage"] then - core.setting_set("enable_damage", fields["cb_enable_damage"]) - local selected = core.get_textlist_index("sp_worlds") - if selected then - local filename = menudata.worldlist:get_list()[selected].path .. - DIR_DELIM .. "world.mt" - local test = io.open(filename) - if test then - local worldfile = Settings(filename) - worldfile:set("enable_damage", fields["cb_enable_damage"]) - --if not worldfile:write() then - --core.log("error", "Failed to write world config file") - --end - end - end - return true - end + if fields["world_create"] ~= nil then + local create_world_dlg = create_create_world_dlg(true) + create_world_dlg:set_parent(this) + this:hide() + create_world_dlg:show() + mm_texture.update("singleplayer",current_game()) + return true + end - if fields["play"] ~= nil or - world_doubleclick or - fields["key_enter"] then - local selected = core.get_textlist_index("sp_worlds") + 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) + this:hide() + delete_world_dlg:show() + mm_texture.update("singleplayer",current_game()) + end + end - if selected ~= nil then - gamedata.selected_world = menudata.worldlist:get_raw_index(selected) - gamedata.singleplayer = true + return true + end - core.start() - 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 fields["world_create"] ~= nil then - local create_world_dlg = create_create_world_dlg(true) - create_world_dlg:set_parent(this) - this:hide() - create_world_dlg:show() - mm_texture.update("singleplayer",current_game()) - return true - end + if (configdialog ~= nil) then + configdialog:set_parent(this) + this:hide() + configdialog:show() + mm_texture.update("singleplayer",current_game()) + end + 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) - this:hide() - delete_world_dlg:show() - mm_texture.update("singleplayer",current_game()) - end - end + return true + end - return true - end + if fields["cancel"] ~= nil then + this:hide() + this.parent:show() + 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) - this:hide() - configdialog:show() - mm_texture.update("singleplayer",current_game()) - end - end - - return true - end + return false end local function on_change(type, old_tab, new_tab) - local buttonbar = ui.find_by_name("game_button_bar") + 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 ( buttonbar == nil ) then + singleplayer_refresh_gamebar() + buttonbar = ui.find_by_name("game_button_bar") + end - if (type == "ENTER") then - local game = current_game() + if (type == "ENTER") then + local game = current_game() - if game then - menudata.worldlist:set_filtercriteria(game.id) - core.set_topleft_text(game.name) - mm_texture.update("singleplayer",game) - end - buttonbar:show() - else - menudata.worldlist:set_filtercriteria(nil) - buttonbar:hide() - core.set_topleft_text("") - mm_texture.update(new_tab,nil) - end + if game then + menudata.worldlist:set_filtercriteria(game.id) + --core.set_topleft_text(game.name) + mm_texture.update("singleplayer",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 - } - -function create_tab_single() - local retval = dialog_create("singleplayer", - get_formspec, - main_button_handler, - nil) - return retval -end + 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 index 4214ee775..33034bbba 100644 --- a/builtin/mainmenu/tab_texturepacks.lua +++ b/builtin/mainmenu/tab_texturepacks.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2014 sapier -- --This program is free software; you can redistribute it and/or modify @@ -17,102 +17,112 @@ -------------------------------------------------------------------------------- local function filter_texture_pack_list(list) - local retval = {"None"} - for _, item in ipairs(list) do - if item ~= "base" then - table.insert(retval, item) - end - end - return retval + local retval = {"None"} + for _, item in ipairs(list) do + if item ~= "base" then + table.insert(retval, item) + end + end + return retval end -------------------------------------------------------------------------------- local function render_texture_pack_list(list) - local retval = "" + local retval = "" - for i, v in ipairs(list) do - if v:sub(1,1) ~= "." then - if retval ~= "" then - retval = retval .."," - end + for i, v in ipairs(list) do + if v:sub(1,1) ~= "." then + if retval ~= "" then + retval = retval .."," + end - retval = retval .. core.formspec_escape(v) - end - end + retval = retval .. core.formspec_escape(v) + end + end - return retval + return retval end -------------------------------------------------------------------------------- local function get_formspec(tabview, name, tabdata) - - local retval = "label[4,-0.25;".. fgettext("Select texture pack:") .. "]".. - "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")) + local retval = "size[16,11]".. + "bgcolor[#00000070;true]".. + "box[-100,8.5;200,10;#999999]" .. + "box[-100,-10;200,12;#999999]" .. + "label[4,-0.25;".. fgettext("Select texture pack:") .. "]".. + "image_button[12,9.55;4,0.8;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button.png;btn_cancel;".. fgettext("OK") .. ";true;true;"..minetest.formspec_escape(mm_texture.basetexturedir).."menu_button_b.png]".. + "textlist[0,2.0;15.8,6.25;TPs;" - if index == nil then index = 1 end + 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 current_texture_path == "" then - retval = retval .. - render_texture_pack_list(list) .. - ";" .. index .. "]" - return retval - end + if index == nil then index = 1 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 + if current_texture_path == "" then + retval = retval .. + render_texture_pack_list(list) .. + ";" .. index .. ";true]" + return retval + 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 + 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 - return retval .. - render_texture_pack_list(list) .. - ";" .. index .. "]" .. - "image[0.25,0.25;4.0,3.7;"..core.formspec_escape(screenfile or no_screenshot).."]".. - "textarea[0.6,3.25;3.7,1.5;;"..core.formspec_escape(infotext or "")..";]" + 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 .. ";true]" .. + "image[0.25,9.25;4.0,3.7;"..core.formspec_escape(screenfile or no_screenshot).."]".. + "textarea[4.5,9.75;6.7,2.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 + 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 + core.setting_set("texture_path", new_path) + end + end + return true + end + if fields["btn_cancel"] ~= nil then + tabview:hide() + tabview.parent:show() + 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 - } + 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 d7d1c7035..4ecc36430 100644 --- a/builtin/mainmenu/textures.lua +++ b/builtin/mainmenu/textures.lua @@ -1,4 +1,4 @@ ---multicraft +--Minetest --Copyright (C) 2013 sapier -- --This program is free software; you can redistribute it and/or modify @@ -20,147 +20,143 @@ mm_texture = {} -------------------------------------------------------------------------------- function mm_texture.init() - mm_texture.defaulttexturedir = core.get_texturepath() .. DIR_DELIM .. "base" .. - DIR_DELIM .. "pack" .. DIR_DELIM - mm_texture.basetexturedir = mm_texture.defaulttexturedir - - mm_texture.texturepack = core.setting_get("texture_path") - - mm_texture.gameid = nil + mm_texture.defaulttexturedir = core.get_texturepath() .. DIR_DELIM .. "base" .. + DIR_DELIM .. "pack" .. DIR_DELIM + mm_texture.basetexturedir = mm_texture.defaulttexturedir + + mm_texture.texturepack = core.setting_get("texture_path") + + mm_texture.gameid = nil end -------------------------------------------------------------------------------- function mm_texture.update(tab,gamedetails) - if tab ~= "singleplayer" then - mm_texture.reset() - return - end + if gamedetails == nil then + return + end - if gamedetails == nil then - return - end - - mm_texture.update_game(gamedetails) + mm_texture.update_game(gamedetails) end -------------------------------------------------------------------------------- function mm_texture.reset() - mm_texture.gameid = nil - local have_bg = false - local have_overlay = mm_texture.set_generic("overlay") - - if not have_overlay then - have_bg = mm_texture.set_generic("background") - end - - mm_texture.clear("header") - mm_texture.clear("footer") - core.set_clouds(false) - - mm_texture.set_generic("footer") - mm_texture.set_generic("header") - - if not have_bg then - if core.setting_getbool("menu_clouds") then - core.set_clouds(true) - else - mm_texture.set_dirt_bg() - end - end + mm_texture.gameid = nil + local have_bg = false + local have_overlay = mm_texture.set_generic("overlay") + + if not have_overlay then + have_bg = mm_texture.set_generic("background") + end + + mm_texture.clear("header") + mm_texture.clear("footer") + core.set_clouds(false) + + mm_texture.set_generic("footer") + mm_texture.set_generic("header") + + if not have_bg then + if core.setting_getbool("menu_clouds") then + core.set_clouds(true) + else + mm_texture.set_dirt_bg() + end + end end -------------------------------------------------------------------------------- function mm_texture.update_game(gamedetails) - if mm_texture.gameid == gamedetails.id then - return - end - - local have_bg = false - local have_overlay = mm_texture.set_game("overlay",gamedetails) - - if not have_overlay then - have_bg = mm_texture.set_game("background",gamedetails) - end - - mm_texture.clear("header") - mm_texture.clear("footer") - core.set_clouds(false) - - if not have_bg then - - if core.setting_getbool("menu_clouds") then - core.set_clouds(true) - else - mm_texture.set_dirt_bg() - end - end - - mm_texture.set_game("footer",gamedetails) - mm_texture.set_game("header",gamedetails) - - mm_texture.gameid = gamedetails.id + if mm_texture.gameid == gamedetails.id then + return + end + + local have_bg = false + local have_overlay = mm_texture.set_game("overlay",gamedetails) + + if not have_overlay then + have_bg = mm_texture.set_game("background",gamedetails) + end + + mm_texture.clear("header") + mm_texture.clear("footer") + core.set_clouds(false) + + if not have_bg then + + if core.setting_getbool("menu_clouds") then + core.set_clouds(true) + else + mm_texture.set_dirt_bg() + end + end + + mm_texture.set_game("footer",gamedetails) + --print(dump(gamedetails)) + mm_texture.set_game("header",gamedetails) + + mm_texture.gameid = gamedetails.id end -------------------------------------------------------------------------------- function mm_texture.clear(identifier) - core.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_" .. - identifier .. ".png" - 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_" .. - identifier .. ".png" - if core.set_background(identifier,path) then - return true - end - end - - return false + --try texture pack first + if mm_texture.texturepack ~= nil then + local path = mm_texture.texturepack .. DIR_DELIM .."menu_" .. + identifier .. ".png" + 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_" .. + identifier .. ".png" + if core.set_background(identifier,path) then + return true + end + end + + return false end -------------------------------------------------------------------------------- function mm_texture.set_game(identifier,gamedetails) - - if gamedetails == nil then - return false - end - if mm_texture.texturepack ~= nil then - local path = mm_texture.texturepack .. DIR_DELIM .. - gamedetails.id .. "_menu_" .. identifier .. ".png" - if core.set_background(identifier,path) then - return true - end - end - - local path = gamedetails.path .. DIR_DELIM .."menu" .. - DIR_DELIM .. identifier .. ".png" - if core.set_background(identifier,path) then - return true - end - - return false + if gamedetails == nil then + return false + end + + if mm_texture.texturepack ~= nil then + local path = mm_texture.texturepack .. DIR_DELIM .. + gamedetails.id .. "_menu_" .. identifier .. ".png" + if core.set_background(identifier,path) then + return true + end + end + + local path = gamedetails.path .. DIR_DELIM .."menu" .. + DIR_DELIM .. identifier .. ".png" + if core.set_background(identifier,path) then + return true + end + + return false end function mm_texture.set_dirt_bg() - if mm_texture.texturepack ~= nil then - local path = mm_texture.texturepack .. DIR_DELIM .."default_dirt.png" - if core.set_background("background", path, true, 128) then - return true - end - end - - --use base pack - local minimalpath = defaulttexturedir .. "dirt_bg.png" - core.set_background("background", minimalpath, true, 128) + if mm_texture.texturepack ~= nil then + local path = mm_texture.texturepack .. DIR_DELIM .."default_stone.png" + if core.set_background("background", path, true, 128) then + return true + end + end + + --use base pack + local minimalpath = defaulttexturedir .. "dirt_bg.png" + core.set_background("background", minimalpath, true, 128) end diff --git a/builtin/profiler.lua b/builtin/profiler.lua new file mode 100644 index 000000000..070c45ed8 --- /dev/null +++ b/builtin/profiler.lua @@ -0,0 +1,66 @@ +local ffi + +-- there's no ffi in Lua, only in LuaJIT +-- when Freeminer is run with Lua the profiler is not available because we can't access precise timer +if not pcall(function() ffi = require("ffi") end) then + return +end + +ffi.cdef[[ +unsigned int get_time_us(); +]] + +local modpath = core.get_builtin_path()..DIR_DELIM + +package.path = package.path .. ";" .. modpath .. "/?.lua" +ProFi = require 'ProFi' + +local function get_time_precise() + return ffi.C.get_time_us() / 1000000 +end + +ProFi:setGetTimeMethod(get_time_precise) + +local started = false + +local function start_profiler() + ProFi:start() + started = true +end + +if freeminer.setting_getbool("profiler_autostart") then + start_profiler() + freeminer.after(3, function() + freeminer.chat_send_all("The profiler was started. If you don't want this, set " .. freeminer.colorize("61ad6d", "profiler_autostart") + .. " to false in " .. freeminer.colorize("61ad6d", "freeminer.conf")) + end) +end + +freeminer.register_chatcommand("profiler_stop", { + description = "stop the profiler and write report", + privs = {server=true}, + func = function(name) + if not started then + freeminer.chat_send_player(name, "Profiler has not been started. You can start it using " .. freeminer.colorize("00ffff", "/profiler_start")) + return + end + + ProFi:stop() + ProFi:writeReport("profile.txt") + + freeminer.chat_send_player(name, "Profiler is stopped.") + end, +}) + +freeminer.register_chatcommand("profiler_start", { + description = "start the profiler", + privs = {server=true}, + func = function(name) + if started then + freeminer.chat_send_player(name, "Profiler is already running.") + return + end + start_profiler() + freeminer.chat_send_player(name, "Profiler is started.") + end +})