From 6227f9c72c6041c5407f854451283b09807422f6 Mon Sep 17 00:00:00 2001 From: MoNTE48 Date: Thu, 6 Aug 2020 20:33:21 +0200 Subject: [PATCH] Add MultiCraft MainMenu --- builtin/fstk/buttonbar.lua | 6 +- builtin/fstk/dialog.lua | 13 +- builtin/fstk/tabview.lua | 24 +- builtin/fstk/ui.lua | 56 +++- builtin/mainmenu/async_event.lua | 2 - builtin/mainmenu/common.lua | 126 ++++---- builtin/mainmenu/dlg_config_world.lua | 6 +- builtin/mainmenu/dlg_contentstore.lua | 13 +- builtin/mainmenu/dlg_create_world.lua | 18 +- builtin/mainmenu/dlg_create_world_default.lua | 151 +++++++++ builtin/mainmenu/dlg_delete_content.lua | 9 +- builtin/mainmenu/dlg_delete_world.lua | 41 ++- builtin/mainmenu/dlg_rename_modpack.lua | 6 +- builtin/mainmenu/dlg_settings_advanced.lua | 10 +- .../mainmenu/generate_from_settingtypes.lua | 1 - builtin/mainmenu/init.lua | 159 +++++----- builtin/mainmenu/pkgmgr.lua | 35 ++- builtin/mainmenu/tab_content.lua | 13 +- builtin/mainmenu/tab_credits.lua | 35 ++- builtin/mainmenu/tab_local.lua | 289 ++++++++++-------- builtin/mainmenu/tab_local_default.lua | 237 ++++++++++++++ builtin/mainmenu/tab_online.lua | 140 ++++++--- builtin/mainmenu/tab_settings.lua | 65 +--- builtin/mainmenu/tab_simple_main.lua | 220 ------------- builtin/mainmenu/textures.lua | 28 +- builtin/settingtypes.txt | 6 +- textures/base/pack/bg.png | Bin 0 -> 8482 bytes textures/base/pack/bg_common.png | Bin 0 -> 162 bytes textures/base/pack/bg_local.png | Bin 0 -> 4805 bytes textures/base/pack/bg_online.png | Bin 0 -> 2676 bytes textures/base/pack/btn_play.png | Bin 0 -> 677 bytes textures/base/pack/creative_bg.png | Bin 0 -> 418 bytes textures/base/pack/creative_bg_ru.png | Bin 0 -> 5351 bytes textures/base/pack/creative_checkbox.png | Bin 0 -> 217 bytes textures/base/pack/logo.png | Bin 12188 -> 0 bytes textures/base/pack/menu_bg.png | Bin 124 -> 0 bytes textures/base/pack/menu_header.png | Bin 1628 -> 0 bytes textures/base/pack/online_mobile.png | Bin 0 -> 192 bytes textures/base/pack/online_pc.png | Bin 0 -> 219 bytes textures/base/pack/refresh.png | Bin 3660 -> 279 bytes textures/base/pack/search.png | Bin 0 -> 241 bytes textures/base/pack/server_flags_creative.png | Bin 273 -> 264 bytes textures/base/pack/server_flags_damage.png | Bin 713 -> 213 bytes textures/base/pack/server_flags_favorite.png | Bin 916 -> 285 bytes textures/base/pack/server_flags_mc.png | Bin 0 -> 202 bytes textures/base/pack/server_flags_mt.png | Bin 0 -> 432 bytes textures/base/pack/server_flags_pvp.png | Bin 1048 -> 262 bytes textures/base/pack/server_ping_1.png | Bin 251 -> 118 bytes textures/base/pack/server_ping_2.png | Bin 244 -> 122 bytes textures/base/pack/server_ping_3.png | Bin 245 -> 122 bytes textures/base/pack/server_ping_4.png | Bin 213 -> 114 bytes textures/base/pack/trash.png | Bin 0 -> 232 bytes 52 files changed, 1002 insertions(+), 707 deletions(-) create mode 100644 builtin/mainmenu/dlg_create_world_default.lua create mode 100644 builtin/mainmenu/tab_local_default.lua delete mode 100644 builtin/mainmenu/tab_simple_main.lua create mode 100644 textures/base/pack/bg.png create mode 100644 textures/base/pack/bg_common.png create mode 100644 textures/base/pack/bg_local.png create mode 100644 textures/base/pack/bg_online.png create mode 100644 textures/base/pack/btn_play.png create mode 100644 textures/base/pack/creative_bg.png create mode 100644 textures/base/pack/creative_bg_ru.png create mode 100644 textures/base/pack/creative_checkbox.png delete mode 100644 textures/base/pack/logo.png delete mode 100644 textures/base/pack/menu_bg.png delete mode 100644 textures/base/pack/menu_header.png create mode 100644 textures/base/pack/online_mobile.png create mode 100644 textures/base/pack/online_pc.png create mode 100644 textures/base/pack/search.png create mode 100644 textures/base/pack/server_flags_mc.png create mode 100644 textures/base/pack/server_flags_mt.png create mode 100644 textures/base/pack/trash.png diff --git a/builtin/fstk/buttonbar.lua b/builtin/fstk/buttonbar.lua index 465588324..cb8bb5ac5 100644 --- a/builtin/fstk/buttonbar.lua +++ b/builtin/fstk/buttonbar.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -34,7 +34,7 @@ local function buttonbar_formspec(self) (i - self.startbutton) * self.btn_size + --button offset self.btn_initial_offset else - btn_pos.x = self.pos.x + (self.btn_size * 0.05) + btn_pos.x = self.pos.x + (self.btn_size * 0.1) end if self.orientation == "vertical" then @@ -187,7 +187,7 @@ function buttonbar_create(name, cbf_buttonhandler, pos, orientation, size) local self = {} self.name = name self.type = "addon" - self.bgcolor = "#000000" + self.bgcolor = "#8fb9de" self.pos = pos self.size = size self.orientation = orientation diff --git a/builtin/fstk/dialog.lua b/builtin/fstk/dialog.lua index ea57df1d2..a7bdbbf57 100644 --- a/builtin/fstk/dialog.lua +++ b/builtin/fstk/dialog.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --this program is distributed in the hope that it will be useful, @@ -69,14 +69,15 @@ function dialog_create(name,get_formspec,buttonhandler,eventhandler) end function messagebox(name, message) + local bg = core.formspec_escape(defaulttexturedir .. "bg_common.png") return dialog_create(name, function() return ([[ - formspec_version[3] - size[8,3] - textarea[0.375,0.375;7.25,1.2;;;%s] - button[3,1.825;2,0.8;ok;%s] - ]]):format(message, fgettext("OK")) + size[12,6,false] + background[0,0;0,0;%s;true;32] + textarea[1,1;10,4;;;%s] + button[5,4.5;2,0.8;ok;%s] + ]]):format(bg, message, fgettext("OK")) end, function(this, fields) if fields.ok then diff --git a/builtin/fstk/tabview.lua b/builtin/fstk/tabview.lua index 3715e231b..f170c7697 100644 --- a/builtin/fstk/tabview.lua +++ b/builtin/fstk/tabview.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -56,24 +56,42 @@ local function add_tab(self,tab) end end +local function get_bg(tsize, tabname) + local bg = + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" + + if tabname then + bg = bg .. + "background[0,0;" .. tsize.width .. "," .. tsize.height .. ";" .. + core.formspec_escape(defaulttexturedir .. + "bg_" .. tabname .. ".png") .. ";true]" + end + + return bg +end + -------------------------------------------------------------------------------- local function get_formspec(self) local formspec = "" if not self.hidden and (self.parent == nil or not self.parent.hidden) then + local name = self.tablist[self.last_tab_index].name + local tabname = (name == "local" or name == "online") and name + or (name == "local_default" and "local") if self.parent == nil then local tsize = self.tablist[self.last_tab_index].tabsize or {width=self.width, height=self.height} formspec = formspec .. string.format("size[%f,%f,%s]",tsize.width,tsize.height, - dump(self.fixed_size)) + dump(self.fixed_size)) .. get_bg(tsize, tabname) end formspec = formspec .. self:tab_header() formspec = formspec .. self.tablist[self.last_tab_index].get_formspec( self, - self.tablist[self.last_tab_index].name, + name, self.tablist[self.last_tab_index].tabdata, self.tablist[self.last_tab_index].tabsize ) diff --git a/builtin/fstk/ui.lua b/builtin/fstk/ui.lua index 6d26aabf0..c12961927 100644 --- a/builtin/fstk/ui.lua +++ b/builtin/fstk/ui.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -54,38 +54,70 @@ end -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- +local maintab = core.settings:get("maintab_LAST") +local connect_time = tonumber(core.settings:get("connect_time")) + function ui.update() local formspec = {} + -- attempt auto restart +--[[if gamedata ~= nil and gamedata.errormessage ~= nil and + core.settings:get_bool("auto_connect") == true and + connect_time and connect_time < os.time() - 30 and + not gamedata.errormessage:find("Kicked") then + if maintab == "local" or maintab == "local_default" then + gamedata.singleplayer = true + gamedata.selected_world = + tonumber(core.settings:get("mainmenu_last_selected_world")) + end + core.settings:set("connect_time", os.time()) + gamedata.reconnect_requested = false + gamedata.errormessage = nil + gamedata.do_reconnect = true + core.start() + return + end]] + -- handle errors if gamedata ~= nil and gamedata.reconnect_requested then local error_message = core.formspec_escape( gamedata.errormessage or "") formspec = { - "size[14,8]", - "real_coordinates[true]", + "formspec_version[3]", + "size[14,8.25]", + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]", "box[0.5,1.2;13,5;#000]", ("textarea[0.5,1.2;13,5;;%s;%s]"):format( fgettext("The server has requested a reconnect:"), error_message), "button[2,6.6;4,1;btn_reconnect_yes;" .. fgettext("Reconnect") .. "]", - "button[8,6.6;4,1;btn_reconnect_no;" .. fgettext("Main menu") .. "]" + "button[8,6.6;4,1;btn_reconnect_no;" .. fgettext("Close") .. "]" } elseif gamedata ~= nil and gamedata.errormessage ~= nil then local error_message = core.formspec_escape(gamedata.errormessage) local error_title - if string.find(gamedata.errormessage, "ModError") then + if gamedata.errormessage:find("ModError") then error_title = fgettext("An error occurred in a Lua script:") else error_title = fgettext("An error occurred:") end + local restart_btn = "button[5,6.6;4,1;btn_reconnect_no;" .. fgettext("Close") .. "]" + if maintab == "local" or maintab == "local_default" and + connect_time and connect_time < os.time() - 30 then + restart_btn = + "button[2,6.6;4,1;btn_reconnect_yes;" .. fgettext("Restart") .. "]" .. + "button[8,6.6;4,1;btn_reconnect_no;" .. fgettext("Close") .. "]" + end formspec = { - "size[14,8]", - "real_coordinates[true]", + "formspec_version[3]", + "size[14,8.25]", + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]", "box[0.5,1.2;13,5;#000]", ("textarea[0.5,1.2;13,5;;%s;%s]"):format( error_title, error_message), - "button[5,6.6;4,1;btn_error_confirm;" .. fgettext("OK") .. "]" + restart_btn } else local active_toplevel_ui_elements = 0 @@ -164,12 +196,18 @@ end -------------------------------------------------------------------------------- core.button_handler = function(fields) if fields["btn_reconnect_yes"] then + if maintab == "local" or maintab == "local_default" then + gamedata.singleplayer = true + gamedata.selected_world = + tonumber(core.settings:get("mainmenu_last_selected_world")) + end + core.settings:set("connect_time", os.time()) gamedata.reconnect_requested = false gamedata.errormessage = nil gamedata.do_reconnect = true core.start() return - elseif fields["btn_reconnect_no"] or fields["btn_error_confirm"] then + elseif fields["btn_reconnect_no"] then gamedata.errormessage = nil gamedata.reconnect_requested = false ui.update() diff --git a/builtin/mainmenu/async_event.lua b/builtin/mainmenu/async_event.lua index 04bfb78d6..1cb657ff5 100644 --- a/builtin/mainmenu/async_event.lua +++ b/builtin/mainmenu/async_event.lua @@ -1,4 +1,3 @@ - core.async_jobs = {} local function handle_job(jobid, serialized_retval) @@ -29,4 +28,3 @@ function core.handle_async(func, parameter, callback) return true end - diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index 782d6973f..aed36ff4f 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -35,54 +35,59 @@ common_update_cached_supp_proto() -------------------------------------------------------------------------------- local function render_client_count(n) - if n > 99 then return '99+' + if n > 999 then return '999' elseif n >= 0 then return tostring(n) else return '?' end end -local function configure_selected_world_params(idx) - local worldconfig = pkgmgr.get_worldconfig(menudata.worldlist:get_list()[idx].path) - if worldconfig.creative_mode then - core.settings:set("creative_mode", worldconfig.creative_mode) - end - if worldconfig.enable_damage then - core.settings:set("enable_damage", worldconfig.enable_damage) - end -end - -------------------------------------------------------------------------------- -function image_column(tooltip, flagname) +function image_column(tooltip) return "image,tooltip=" .. core.formspec_escape(tooltip) .. "," .. "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. - "1=" .. core.formspec_escape(defaulttexturedir .. - (flagname and "server_flags_" .. flagname .. ".png" or "blank.png")) .. "," .. - "2=" .. core.formspec_escape(defaulttexturedir .. "server_ping_4.png") .. "," .. - "3=" .. core.formspec_escape(defaulttexturedir .. "server_ping_3.png") .. "," .. - "4=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," .. - "5=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png") + "1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_favorite.png") .. "," .. + "2=" .. core.formspec_escape(defaulttexturedir .. "server_flags_mc.png") .. "," .. + "3=" .. core.formspec_escape(defaulttexturedir .. "server_flags_mt.png") .. "," .. + "4=" .. core.formspec_escape(defaulttexturedir .. "server_flags_damage.png") .. "," .. + "5=" .. core.formspec_escape(defaulttexturedir .. "server_flags_creative.png") .. "," .. + "6=" .. core.formspec_escape(defaulttexturedir .. "server_flags_pvp.png") .. "," .. + "14=" .. core.formspec_escape(defaulttexturedir .. "server_ping_4.png") .. "," .. + "13=" .. core.formspec_escape(defaulttexturedir .. "server_ping_3.png") .. "," .. + "12=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," .. + "11=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png") end -------------------------------------------------------------------------------- -function order_favorite_list(list) +function order_favorite_list(list, mobile) local res = {} - --orders the favorite list after support + local non_mobile_servers = {} + -- orders the multicraft list before support for i = 1, #list do local fav = list[i] - if is_server_protocol_compat(fav.proto_min, fav.proto_max) then + if mobile and not fav.mobile_friendly then + non_mobile_servers[("%s:%s"):format(fav.address, fav.port)] = fav + elseif fav.server_id == "multicraft" then res[#res + 1] = fav end end for i = 1, #list do local fav = list[i] - if not is_server_protocol_compat(fav.proto_min, fav.proto_max) then + if (mobile and fav.mobile_friendly or not mobile) and + is_server_protocol_compat(fav.proto_min, fav.proto_max) and + fav.server_id ~= "multicraft" then res[#res + 1] = fav end end - return res + return res, non_mobile_servers end -------------------------------------------------------------------------------- -function render_serverlist_row(spec, is_favorite) +function render_serverlist_row(spec, is_favorite, is_approved) + -- Get information from non_mobile_servers. + if is_favorite and not spec.proto_min and menudata.non_mobile_servers then + local id = ("%s:%s"):format(spec.address, spec.port) + spec = menudata.non_mobile_servers[id] or spec + end + local text = "" if spec.name then text = text .. core.formspec_escape(spec.name:trim()) @@ -99,19 +104,23 @@ function render_serverlist_row(spec, is_favorite) if is_favorite then details = "1," else - details = "0," + if is_approved then + details = "2," + else + details = "3," + end end - if spec.ping then - local ping = spec.ping * 1000 - if ping <= 50 then - details = details .. "2," - elseif ping <= 100 then - details = details .. "3," - elseif ping <= 250 then - details = details .. "4," + if spec.lag then + local lag = spec.lag * 1000 + if lag <= 100 then + details = details .. "14," + elseif lag <= 150 then + details = details .. "13," + elseif lag <= 250 then + details = details .. "12," else - details = details .. "5," + details = details .. "11," end else details = details .. "0," @@ -123,12 +132,12 @@ function render_serverlist_row(spec, is_favorite) -- Choose a color depending on how many clients are connected -- (relatively to clients_max) local clients_color - if grey_out then clients_color = '#aaaaaa' - elseif spec.clients == 0 then clients_color = '' -- 0 players: default/white + if grey_out then clients_color = '#aaaaaa' + elseif spec.clients == 0 then clients_color = '' -- 0 players: default/white elseif clients_percent <= 60 then clients_color = '#a1e587' -- 0-60%: green elseif clients_percent <= 90 then clients_color = '#ffdc97' -- 60-90%: yellow elseif clients_percent == 100 then clients_color = '#dd5b5b' -- full server: red (darker) - else clients_color = '#ffba97' -- 90-100%: orange + else clients_color = '#ffba97' -- 90-100%: orange end details = details .. clients_color .. ',' .. @@ -142,19 +151,11 @@ function render_serverlist_row(spec, is_favorite) end if spec.creative 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," + details = details .. "5," + elseif spec.pvp then + details = details .. "6," + elseif spec.damage then + details = details .. "4," else details = details .. "0," end @@ -200,10 +201,9 @@ function menu_render_worldlist() local retval = "" local current_worldlist = menudata.worldlist:get_list() - for i, v in ipairs(current_worldlist) do + for _, v in ipairs(current_worldlist) do if retval ~= "" then retval = retval .. "," end - retval = retval .. core.formspec_escape(v.name) .. - " \\[" .. core.formspec_escape(v.gameid) .. "\\]" + retval = retval .. core.formspec_escape(v.name) end return retval @@ -220,14 +220,13 @@ function menu_handle_key_up_down(fields, textlist, settingname) newidx = oldidx + 1 end core.settings:set(settingname, menudata.worldlist:get_raw_index(newidx)) - configure_selected_world_params(newidx) return true end return false end -------------------------------------------------------------------------------- -function asyncOnlineFavourites() +function asyncOnlineFavourites(mobile) if not menudata.public_known then menudata.public_known = {{ name = fgettext("Loading..."), @@ -250,11 +249,12 @@ function asyncOnlineFavourites() nil, function(result) menudata.public_downloading = nil - local favs = order_favorite_list(result) + local favs, non_mobile = order_favorite_list(result, mobile) if favs[1] then menudata.public_known = favs menudata.favorites = menudata.public_known menudata.favorites_is_public = true + menudata.non_mobile_servers = non_mobile end core.event_handler("Refresh") end @@ -335,15 +335,3 @@ function menu_worldmt(selected, setting, value) return nil end end - -function menu_worldmt_legacy(selected) - local modes_names = {"creative_mode", "enable_damage", "server_announce"} - for _, mode_name in pairs(modes_names) do - local mode_val = menu_worldmt(selected, mode_name) - if mode_val then - core.settings:set(mode_name, mode_val) - else - menu_worldmt(selected, mode_name, core.settings:get(mode_name)) - end - end -end diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua index 2cf70c9c9..0da87e965 100644 --- a/builtin/mainmenu/dlg_config_world.lua +++ b/builtin/mainmenu/dlg_config_world.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -69,7 +69,9 @@ local function get_formspec(data) local mod = data.list:get_list()[data.selected_mod] or {name = ""} local retval = - "size[11.5,7.5,true]" .. + "size[11.5,7.5,false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. "label[0.5,0;" .. fgettext("World:") .. "]" .. "label[1.75,0;" .. data.worldspec.name .. "]" diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 01c42be0b..8c23052dc 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -95,6 +95,9 @@ local function start_install(calling_dialog, package) elseif package.type == "game" then conf_path = path .. DIR_DELIM .. "game.conf" name_is_title = true + + ui.childlist = {} + menudata.init_tabs() elseif package.type == "txp" then conf_path = path .. DIR_DELIM .. "texture_pack.conf" end @@ -319,7 +322,9 @@ function store.get_formspec(dlgdata) if #store.packages_full > 0 then formspec = { "formspec_version[3]", - "size[15.75,9.5]", + "size[15.75,9.5;false]", + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]", "position[0.5,0.55]", "container[0.375,0.375]", "field[0,0;10.225,0.8;search_string;;", core.formspec_escape(search_string), "]", @@ -351,7 +356,9 @@ function store.get_formspec(dlgdata) end else formspec = { - "size[12,7]", + "size[12,7;false]", + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]", "position[0.5,0.55]", "label[4,3;", fgettext("No packages could be retrieved"), "]", "container[0,", H - 0.8 - 0.375, "]", diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 36df23cce..ffa78acbc 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -96,7 +96,9 @@ local function create_world_formspec(dialogdata) -- Error out when no games found if #pkgmgr.games == 0 then - return "size[12.25,3,true]" .. + return "size[12.25,3,false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. "box[0,0;12,2;#ff8800]" .. "textarea[0.3,0;11.7,2;;;".. fgettext("You have no games installed.") .. "\n" .. @@ -131,7 +133,7 @@ local function create_world_formspec(dialogdata) end end - local game_by_gameidx = core.get_game(gameidx) + local game_by_gameidx = pkgmgr.get_game_no_default(gameidx) local disallowed_mapgen_settings = {} if game_by_gameidx ~= nil then local gamepath = game_by_gameidx.path @@ -316,7 +318,9 @@ local function create_world_formspec(dialogdata) end local retval = - "size[12.25,7,true]" .. + "size[12.25,7,false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. -- Left side "container[0,0]".. @@ -363,9 +367,7 @@ local function create_world_buttonhandler(this, fields) if gameindex ~= nil then if worldname == "" then - local random_number = math.random(10000, 99999) - local random_world_name = "Unnamed" .. random_number - worldname = random_world_name + worldname = "World " .. math.random(1000, 9999) end core.settings:set("fixed_map_seed", fields["te_seed"]) @@ -373,7 +375,7 @@ local function create_world_buttonhandler(this, fields) local message if not menudata.worldlist:uid_exists_raw(worldname) then core.settings:set("mg_name",fields["dd_mapgen"]) - message = core.create_world(worldname,gameindex) + message = pkgmgr.create_world_no_default(worldname,gameindex) else message = fgettext("A world named \"$1\" already exists", worldname) end diff --git a/builtin/mainmenu/dlg_create_world_default.lua b/builtin/mainmenu/dlg_create_world_default.lua new file mode 100644 index 000000000..d93cdb9f1 --- /dev/null +++ b/builtin/mainmenu/dlg_create_world_default.lua @@ -0,0 +1,151 @@ +--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 3.0 of the License, or +--(at your option) any later version. +-- +--This program is distributed in the hope that it will be useful, +--but WITHOUT ANY WARRANTY; without even the implied warranty of +--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +--GNU Lesser General Public License for more details. +-- +--You should have received a copy of the GNU Lesser General Public License along +--with this program; if not, write to the Free Software Foundation, Inc., +--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +local function create_world_formspec() + local mapgens = core.get_mapgen_names() + + local current_seed = core.settings:get("fixed_map_seed") or "" + local current_mg = core.settings:get("mg_name") + local gameid = core.settings:get("menu_last_game") + + local gameidx = 0 + if gameid ~= nil then + local _ + _, gameidx = pkgmgr.find_by_gameid(gameid) + + if gameidx == nil then + gameidx = 0 + end + end + + local game_by_gameidx = core.get_game(gameidx) + if game_by_gameidx ~= nil then + local allowed_mapgens = {"v7p", "flat", "valleys"} + for key, value in pairs(allowed_mapgens) do + allowed_mapgens[key] = value:trim() + end + + if #allowed_mapgens > 0 then + for i = #mapgens, 1, -1 do + if table.indexof(allowed_mapgens, mapgens[i]) == -1 then + table.remove(mapgens, i) + end + end + end + end + + local mglist = "" + local selindex = 1 + local i = 1 + for _, 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 = + "size[12,6,false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. + "label[1.5,1.2;" .. fgettext("World name") .. ":" .. "]".. + "field[4.5,1.5;6,0.5;te_world_name;;]" .. + + "label[1.5,2.2;" .. fgettext("Seed") .. ":" .. "]".. + "field[4.5,2.5;6,0.5;te_seed;;".. current_seed .. "]" .. + + "label[1.5,3.2;" .. fgettext("Mapgen") .. ":" .. "]".. + "dropdown[4.2,3.05;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" .. + + "style[world_create_confirm;bgcolor=#00d12b]" .. + "button[3.5,4.8;2.5,0.5;world_create_confirm;" .. fgettext("Create") .. "]" .. + "button[6,4.8;2.5,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" + + return retval + +end + +local function create_world_buttonhandler(this, fields) + if fields["world_create_confirm"] or + fields["key_enter"] then + local worldname = fields["te_world_name"] + local gameid = core.settings:get("menu_last_game") + local gameindex = 0 + if gameid ~= nil then + local _ + _, gameindex = pkgmgr.find_by_gameid(gameid) + + if gameindex == nil then + gameindex = 0 + end + end + + if gameindex ~= 0 then + if worldname == "" then + worldname = "World " .. math.random(1000, 9999) + end + + core.settings:set("fixed_map_seed", fields["te_seed"]) + + local message + if not menudata.worldlist:uid_exists_raw(worldname) then + core.settings:set("mg_name",fields["dd_mapgen"]) + message = core.create_world(worldname,gameindex) + else + message = fgettext("A world named \"$1\" already exists", worldname) + end + + if message ~= nil then + gamedata.errormessage = message + else + if this.data.update_worldlist_filter then + menudata.worldlist:set_filtercriteria(pkgmgr.games[gameindex].id) + mm_texture.update("singleplayer", pkgmgr.games[gameindex].id) + end + menudata.worldlist:refresh() + core.settings:set("mainmenu_last_selected_world", + menudata.worldlist:raw_index_by_uid(worldname)) + end + else + gamedata.errormessage = fgettext("No game selected") + end + + this:delete() + return true + end + + + if fields["world_create_cancel"] then + this:delete() + return true + end + + return false +end + + +function create_create_world_default_dlg(update_worldlistfilter) + local retval = dialog_create("sp_create_world", + create_world_formspec, + create_world_buttonhandler, + nil) + retval.update_worldlist_filter = update_worldlistfilter + + return retval +end diff --git a/builtin/mainmenu/dlg_delete_content.lua b/builtin/mainmenu/dlg_delete_content.lua index a24171541..ce609827f 100644 --- a/builtin/mainmenu/dlg_delete_content.lua +++ b/builtin/mainmenu/dlg_delete_content.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -19,7 +19,9 @@ local function delete_content_formspec(dialogdata) local retval = - "size[11.5,4.5,true]" .. + "size[11.5,4.5,false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. "label[2,2;" .. fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name) .. "]".. "style[dlg_delete_content_confirm;bgcolor=red]" .. @@ -44,6 +46,9 @@ local function delete_content_buttonhandler(this, fields) if this.data.content.type == "game" then pkgmgr.update_gamelist() + + ui.childlist = {} + menudata.init_tabs() else pkgmgr.refresh_globals() end diff --git a/builtin/mainmenu/dlg_delete_world.lua b/builtin/mainmenu/dlg_delete_world.lua index 33e7bc945..1028fe151 100644 --- a/builtin/mainmenu/dlg_delete_world.lua +++ b/builtin/mainmenu/dlg_delete_world.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -16,19 +16,35 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +local b = core.formspec_escape(defaulttexturedir .. "blank.png") local function delete_world_formspec(dialogdata) + local game_name = dialogdata.delete_game + local delete_game = (game_name and " [" .. game_name .. "]") or "" + local retval = - "size[10,2.5,true]" .. - "label[0.5,0.5;" .. - fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" .. + "size[12,4,false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. + "image_button[3,0.4;6,0.6;" .. b .. ";;" .. fgettext("Delete World") .. + ";true;false;]" .. + "image_button[3,1;6,0.6;" .. b .. ";;" .. + fgettext("\"$1$2", dialogdata.delete_name, delete_game) .. + "\"?;true;false;]" .. + "image_button[3,0.4;6,1.25;" .. b .. ";;;true;false;]" .. "style[world_delete_confirm;bgcolor=red]" .. - "button[0.5,1.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" .. - "button[7.0,1.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]" + "button[3.5,2.8;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" .. + "button[6,2.8;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]" return retval end local function delete_world_buttonhandler(this, fields) if fields["world_delete_confirm"] then + if this.data.callback then + this:delete() + this.data.callback() + 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) @@ -47,7 +63,7 @@ local function delete_world_buttonhandler(this, fields) end -function create_delete_world_dlg(name_to_del, index_to_del) +function create_delete_world_dlg(name_to_del, index_to_del, game_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") @@ -56,7 +72,18 @@ function create_delete_world_dlg(name_to_del, index_to_del) delete_world_buttonhandler, nil) retval.data.delete_name = name_to_del + retval.data.delete_game = game_to_del retval.data.delete_index = index_to_del return retval end + +function create_custom_delete_dlg(name_to_del, callback) + assert(name_to_del ~= nil and type(name_to_del) == "string" and name_to_del ~= "") + assert(type(callback) == "function") + + local retval = create_delete_world_dlg(name_to_del, -1, nil) + retval.data.callback = callback + + return retval +end diff --git a/builtin/mainmenu/dlg_rename_modpack.lua b/builtin/mainmenu/dlg_rename_modpack.lua index ca76a8cbe..1bcf3dfd8 100644 --- a/builtin/mainmenu/dlg_rename_modpack.lua +++ b/builtin/mainmenu/dlg_rename_modpack.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -19,7 +19,9 @@ local function rename_modpack_formspec(dialogdata) local retval = - "size[11.5,4.5,true]" .. + "size[11.5,4.5,false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. "button[3.25,3.5;2.5,0.5;dlg_rename_modpack_confirm;".. fgettext("Accept") .. "]" .. "button[5.75,3.5;2.5,0.5;dlg_rename_modpack_cancel;".. diff --git a/builtin/mainmenu/dlg_settings_advanced.lua b/builtin/mainmenu/dlg_settings_advanced.lua index f2d9f270f..d5989591d 100644 --- a/builtin/mainmenu/dlg_settings_advanced.lua +++ b/builtin/mainmenu/dlg_settings_advanced.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -783,7 +783,9 @@ local function create_change_setting_formspec(dialogdata) end return ( - "size[" .. width .. "," .. height + 0.25 .. ",true]" .. + "size[" .. width .. "," .. height + 0.25 .. ",false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. create_textfield(description_box, setting_name, comment_text) .. formspec .. "button[" .. width / 2 - 2.5 .. "," .. height - 0.4 .. ";2.5,1;btn_done;" .. @@ -945,7 +947,9 @@ local function handle_change_setting_buttons(this, fields) end local function create_settings_formspec(tabview, _, tabdata) - local formspec = "size[12,5.4;true]" .. + local formspec = "size[12,5.4;false]" .. + "background[0,0;0,0;" .. core.formspec_escape(defaulttexturedir .. + "bg_common.png") .. ";true;32]" .. "tablecolumns[color;tree;text,width=28;text]" .. "tableoptions[background=#00000000;border=false]" .. "field[0.3,0.1;10.2,1;search_string;;" .. core.formspec_escape(search_string) .. "]" .. diff --git a/builtin/mainmenu/generate_from_settingtypes.lua b/builtin/mainmenu/generate_from_settingtypes.lua index 7d36af9d8..a6b5f9988 100644 --- a/builtin/mainmenu/generate_from_settingtypes.lua +++ b/builtin/mainmenu/generate_from_settingtypes.lua @@ -126,4 +126,3 @@ file = assert(io.open("src/settings_translation_file.cpp", "w")) --file = assert(io.open("settings_translation_file.cpp", "w")) file:write(create_translation_file()) file:close() - diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index c17e79270..e3f00623e 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -22,7 +22,7 @@ mt_color_dark_green = "#25C191" local menupath = core.get_mainmenu_path() local basepath = core.get_builtin_path() -local menustyle = core.settings:get("main_menu_style") +local mobile = PLATFORM == "Android" or PLATFORM == "iOS" defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" .. DIR_DELIM .. "pack" .. DIR_DELIM @@ -36,26 +36,36 @@ dofile(menupath .. DIR_DELIM .. "common.lua") dofile(menupath .. DIR_DELIM .. "pkgmgr.lua") dofile(menupath .. DIR_DELIM .. "textures.lua") -dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") -dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua") -dofile(menupath .. DIR_DELIM .. "dlg_contentstore.lua") -if menustyle ~= "simple" then - dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_create_world_default.lua") +dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") + +if not mobile then + dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua") - dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") + dofile(menupath .. DIR_DELIM .. "dlg_contentstore.lua") dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua") + dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua") end local tabs = {} -tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua") -tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua") +if not mobile then + tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua") + tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua") +end + tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua") -if menustyle == "simple" then - tabs.simple_main = dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua") -else - tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua") - tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua") +tabs.local_default_game = dofile(menupath .. DIR_DELIM .. "tab_local_default.lua") +tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua") +tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua") + +local htabs = {} +local hpath = menupath .. DIR_DELIM .. "hosting" .. DIR_DELIM .. "init.lua" +local hosting = io.open(hpath, "r") +if hosting then + htabs = dofile(hpath) + io.close(hosting) end -------------------------------------------------------------------------------- @@ -67,92 +77,77 @@ local function main_event_handler(tabview, event) end -------------------------------------------------------------------------------- -local function init_globals() - -- Init gamedata - gamedata.worldindex = 0 - - if menustyle == "simple" then - local world_list = core.get_worlds() - local world_index - - local found_singleplayerworld = false - for i, world in ipairs(world_list) do - if world.name == "singleplayerworld" then - found_singleplayerworld = true - world_index = i - break - end - end - - if not found_singleplayerworld then - core.create_world("singleplayerworld", 1) - - world_list = core.get_worlds() - - for i, world in ipairs(world_list) do - if world.name == "singleplayerworld" then - world_index = i - break - end - end - end - - gamedata.worldindex = world_index - else - 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.settings:get("menu_last_game") then - local default_game = core.settings:get("default_game") or "minetest" - core.settings:set("menu_last_game", default_game) - end - - mm_texture.init() - end - - -- Create main tabview +function menudata.init_tabs() local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0}) - if menustyle == "simple" then - tv_main:add(tabs.simple_main) - else - tv_main:set_autosave_tab(true) - tv_main:add(tabs.local_game) - tv_main:add(tabs.play_online) + for i = 1, #pkgmgr.games do + if pkgmgr.games[i].id == "default" then + tv_main:add(tabs.local_default_game) + break + end end - tv_main:add(tabs.content) - tv_main:add(tabs.settings) + for i = 1, #pkgmgr.games do + if pkgmgr.games[i].id ~= "default" then + tv_main:add(tabs.local_game) + break + end + end + + for _, page in pairs(htabs) do + tv_main:add(page) + end + tv_main:add(tabs.play_online) + + if not mobile then + tv_main:set_autosave_tab(true) + tv_main:add(tabs.content) + tv_main:add(tabs.settings) + end tv_main:add(tabs.credits) tv_main:set_global_event_handler(main_event_handler) tv_main:set_fixed_size(false) - if menustyle ~= "simple" then + if not mobile then local last_tab = core.settings:get("maintab_LAST") if last_tab and tv_main.current_tab ~= last_tab then tv_main:set_tab(last_tab) end end + ui.set_default("maintab") tv_main:show() ui.update() +end - core.sound_play("main_menu", true) +-------------------------------------------------------------------------------- +local function init_globals() + -- Init gamedata + gamedata.worldindex = 0 + + 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") + + -- Create main tabview + core.set_clouds(false) + mm_texture.set_dirt_bg() + menudata.init_tabs() +-- core.sound_play("main_menu", true) end init_globals() diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua index 5b8807310..88ab48d2b 100644 --- a/builtin/mainmenu/pkgmgr.lua +++ b/builtin/mainmenu/pkgmgr.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -896,19 +896,44 @@ function pkgmgr.get_game(index) return nil end +-------------------------------------------------------------------------------- +local default_game_idx +function pkgmgr.get_game_no_default(index) + if default_game_idx and index >= default_game_idx then + index = index + 1 + end + return pkgmgr.get_game(index) +end + +function pkgmgr.create_world_no_default(worldname, gameindex) + if default_game_idx and gameindex >= default_game_idx then + gameindex = gameindex + 1 + end + return core.create_world(worldname, gameindex) +end + -------------------------------------------------------------------------------- function pkgmgr.update_gamelist() pkgmgr.games = core.get_games() + + -- Update default_game_idx + for i, game in ipairs(pkgmgr.games) do + if game.id == "default" then + default_game_idx = i + break + end + end end -------------------------------------------------------------------------------- function pkgmgr.gamelist() local retval = "" if #pkgmgr.games > 0 then - retval = retval .. core.formspec_escape(pkgmgr.games[1].name) - - for i=2,#pkgmgr.games,1 do - retval = retval .. "," .. core.formspec_escape(pkgmgr.games[i].name) + for i = 1, #pkgmgr.games do + if retval ~= "" then retval = retval .. "," end + if pkgmgr.games[i].id ~= "default" then + retval = retval .. core.formspec_escape(pkgmgr.games[i].name) + end end end return retval diff --git a/builtin/mainmenu/tab_content.lua b/builtin/mainmenu/tab_content.lua index 336730bf4..71da25080 100644 --- a/builtin/mainmenu/tab_content.lua +++ b/builtin/mainmenu/tab_content.lua @@ -4,7 +4,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -30,7 +30,13 @@ local function get_formspec(tabview, name, tabdata) if packages == nil then packages_raw = {} - table.insert_all(packages_raw, pkgmgr.games) + local i = 0 + for _, game in ipairs(pkgmgr.games) do + if game.id ~= "default" then + i = i + 1 + packages_raw[i] = game + end + end table.insert_all(packages_raw, pkgmgr.get_texture_packs()) table.insert_all(packages_raw, pkgmgr.global_mods:get_list()) @@ -136,7 +142,8 @@ local function get_formspec(tabview, name, tabdata) retval = retval .. "textarea[5.85,2.2;6.35,2.9;;" .. fgettext("Information:") .. ";" .. desc .. "]" - if core.may_modify_path(selected_pkg.path) then + if core.may_modify_path(selected_pkg.path) and not + (selected_pkg.type == "game" and selected_pkg.name == "default") then retval = retval .. "button[5.5,4.65;3.25,1;btn_mod_mgr_delete_mod;" .. fgettext("Uninstall Package") .. "]" diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua index c2b7e503a..1f643e02e 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -17,6 +17,19 @@ -------------------------------------------------------------------------------- +local multicraft_developers = { + "Maksim Gamarnik (MoNTE48) ", + "Bektur Mambetov (ubulem) ", + "Alexander Zavrin (Ransom.00)", + "luk3yx", + "An0n3m0us", + "Jean-Patrick Guerrero (kilbith) ", + "Vitaliy Lobachevskiy (numberZero) ", + "sfan5 ", + "Stuart Jones (stujones11) ", + "And other people who helped make the world better!" +} + local core_developers = { "Perttu Ahola (celeron55) ", "sfan5 ", @@ -98,15 +111,19 @@ return { name = "credits", caption = fgettext("Credits"), cbf_formspec = function(tabview, name, tabdata) - local logofile = defaulttexturedir .. "logo.png" local version = core.get_version() - return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" .. - "label[0.5,2.8;" .. version.project .. " " .. version.string .. "]" .. - "button[0.5,3;2,2;homepage;minetest.net]" .. + return "label[0.1,-0.1;" .. + "MultiCraft Open Source Project, ver. " .. version.string .. "\n" .. + "Copyright (C) 2014-2021 MultiCraft Development Team\n" .. + "Licence: LGPLv3.0+ and CC-BY-SA 4.0, Home page: http://multicraft.world\n" .. + "Created and Powered by Minetest Engine, ver. 5.3.0]" .. +-- "button[10,-0.5;2,2;homepage;multicraft.world]" .. "tablecolumns[color;text]" .. - "tableoptions[background=#00000000;highlight=#00000000;border=false]" .. - "table[3.5,-0.25;8.5,6.05;list_credits;" .. - "#FFFF00," .. fgettext("Core Developers") .. ",," .. + "tableoptions[background=#999999;highlight=#00000000;border=true]" .. + "table[0,1.6;11.8,3.8;list_credits;" .. + "#FFFF00," .. fgettext("MultiCraft Developers") .. ",," .. + buildCreditList(multicraft_developers) .. ",,," .. + "#FFFF00," .. fgettext("Minetest Developers") .. ",," .. buildCreditList(core_developers) .. ",,," .. "#FFFF00," .. fgettext("Active Contributors") .. ",," .. buildCreditList(active_contributors) .. ",,," .. @@ -118,7 +135,7 @@ return { end, cbf_button_handler = function(this, fields, name, tabdata) if fields.homepage then - core.open_url("https://www.minetest.net") + core.open_url("http://multicraft.world") end end, } diff --git a/builtin/mainmenu/tab_local.lua b/builtin/mainmenu/tab_local.lua index a21cf12b1..949042062 100644 --- a/builtin/mainmenu/tab_local.lua +++ b/builtin/mainmenu/tab_local.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -15,64 +15,64 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +local lang = core.settings:get("language") +if not lang or lang == "" then lang = os.getenv("LANG") end +local mobile = PLATFORM == "Android" or PLATFORM == "iOS" -local enable_gamebar = PLATFORM ~= "Android" -local current_game, singleplayer_refresh_gamebar -if enable_gamebar then - function current_game() - local last_game_id = core.settings:get("menu_last_game") - local game = pkgmgr.find_by_gameid(last_game_id) +local function current_game() + local last_game_id = core.settings:get("menu_last_game") + local game = pkgmgr.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") + + if old_bar ~= nil then + old_bar:delete() end - function singleplayer_refresh_gamebar() - - local old_bar = ui.find_by_name("game_button_bar") - - if old_bar ~= nil then - old_bar:delete() + local function game_buttonbar_button_handler(fields) + if fields.game_open_cdb then + local maintab = ui.find_by_name("maintab") + local dlg = create_store_dlg("game") + dlg:set_parent(maintab) + maintab:hide() + dlg:show() + return true end - local function game_buttonbar_button_handler(fields) - if fields.game_open_cdb then - local maintab = ui.find_by_name("maintab") - local dlg = create_store_dlg("game") - dlg:set_parent(maintab) - maintab:hide() - dlg:show() - return true - end - - for key,value in pairs(fields) do - for j=1,#pkgmgr.games,1 do - if ("game_btnbar_" .. pkgmgr.games[j].id == key) then - mm_texture.update("singleplayer", pkgmgr.games[j]) - core.set_topleft_text(pkgmgr.games[j].name) - core.settings:set("menu_last_game",pkgmgr.games[j].id) - menudata.worldlist:set_filtercriteria(pkgmgr.games[j].id) - local index = filterlist.get_current_index(menudata.worldlist, - tonumber(core.settings:get("mainmenu_last_selected_world"))) - if not index or index < 1 then - local selected = core.get_textlist_index("sp_worlds") - if selected ~= nil and selected < #menudata.worldlist:get_list() then - index = selected - else - index = #menudata.worldlist:get_list() - end + for key, value in pairs(fields) do + for j=1, #pkgmgr.games do + if ("game_btnbar_" .. pkgmgr.games[j].id == key) then + mm_texture.update("singleplayer", pkgmgr.games[j]) + -- core.set_topleft_text(pkgmgr.games[j].name) + core.settings:set("menu_last_game",pkgmgr.games[j].id) + menudata.worldlist:set_filtercriteria(pkgmgr.games[j].id) + --[[local index = filterlist.get_current_index(menudata.worldlist, + tonumber(core.settings:get("mainmenu_last_selected_world"))) + if not index or index < 1 then + local selected = core.get_table_index("sp_worlds") + if selected ~= nil and selected < #menudata.worldlist:get_list() then + index = selected + else + index = #menudata.worldlist:get_list() end - menu_worldmt_legacy(index) - return true - end + end]] + + return true end end end + end - local btnbar = buttonbar_create("game_button_bar", - game_buttonbar_button_handler, - {x=-0.3,y=5.9}, "horizontal", {x=12.4,y=1.15}) + local btnbar = buttonbar_create("game_button_bar", + game_buttonbar_button_handler, + {x=-1.35, y=-0.32}, "vertical", {x=1, y=6.14}) - for i=1,#pkgmgr.games,1 do + for i=1, #pkgmgr.games do + if pkgmgr.games[i].id ~= "default" then local btn_name = "game_btnbar_" .. pkgmgr.games[i].id local image = nil @@ -83,7 +83,6 @@ if enable_gamebar then pkgmgr.games[i].menuicon_path ~= "" then image = core.formspec_escape(pkgmgr.games[i].menuicon_path) else - local part1 = pkgmgr.games[i].id:sub(1,5) local part2 = pkgmgr.games[i].id:sub(6,10) local part3 = pkgmgr.games[i].id:sub(11) @@ -94,81 +93,104 @@ if enable_gamebar then text = text .. "\n" .. part3 end end + btnbar:add_button(btn_name, text, image, tooltip) end + end + if not mobile then local plus_image = core.formspec_escape(defaulttexturedir .. "plus.png") btnbar:add_button("game_open_cdb", "", plus_image, fgettext("Install games from ContentDB")) end -else - function current_game() - return nil +end + +local function filter_default() + local gameid = core.settings:get("menu_last_game") + if not gameid or gameid == "" or gameid == "default" then + for j=1, #pkgmgr.games do + local name = pkgmgr.games[j].id + if name and name ~= "default" then + menudata.worldlist:set_filtercriteria(name) + core.settings:set("menu_last_game", name) + mm_texture.update("singleplayer", current_game()) + return + end + end end end -local function get_formspec(tabview, name, tabdata) - local retval = "" - +local function get_formspec() + filter_default() local index = filterlist.get_current_index(menudata.worldlist, - tonumber(core.settings:get("mainmenu_last_selected_world")) - ) + tonumber(core.settings:get("mainmenu_last_selected_world"))) - retval = retval .. - "button[4,3.95;2.6,1;world_delete;".. fgettext("Delete") .. "]" .. - "button[6.5,3.95;2.8,1;world_configure;".. fgettext("Configure") .. "]" .. - "button[9.2,3.95;2.5,1;world_create;".. fgettext("New") .. "]" .. - "label[4,-0.25;".. fgettext("Select World:") .. "]".. - "checkbox[0.25,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" .. - dump(core.settings:get_bool("creative_mode")) .. "]".. - "checkbox[0.25,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. - dump(core.settings:get_bool("enable_damage")) .. "]".. - "checkbox[0.25,1.15;cb_server;".. fgettext("Host Server") ..";" .. - dump(core.settings:get_bool("enable_server")) .. "]" .. - "textlist[4,0.25;7.5,3.7;sp_worlds;" .. + local creative_checkbox = core.settings:get_bool("creative_mode") and + "creative_checkbox" or "blank" + + local creative_bg = "creative_bg.png" + if lang and lang == "ru" then + creative_bg = "creative_bg_" .. lang .. ".png" + end + + local retval = + "image_button[0,4.84;3.31,0.92;" .. + core.formspec_escape(defaulttexturedir .. + "blank.png") .. ";world_delete;;true;false]" .. + "tooltip[world_delete;".. fgettext("Delete") .. "]" .. + "image_button[3.14,4.84;3.3,0.92;" .. + core.formspec_escape(defaulttexturedir .. + "blank.png") .. ";world_create;;true;false]" .. + "tooltip[world_create;".. fgettext("New") .. "]" .. + "button[9.5,4.8;2.5,1;world_configure;".. fgettext("Configure") .. "]" .. + + "image_button[6.72,1.43;4.96,1.41;" .. + core.formspec_escape(defaulttexturedir .. + "blank.png") .. ";play;;true;false]" .. + "tooltip[play;".. fgettext("Play Game") .. "]" .. + + "image_button[7.2,3.09;4,0.83;" .. + core.formspec_escape(defaulttexturedir) .. creative_bg .. + ";;;true;false]" .. + "image_button[7.2,3.09;4,0.83;" .. + core.formspec_escape(defaulttexturedir) .. creative_checkbox .. + ".png;cb_creative_mode;;true;false]" .. + + "tableoptions[background=#27233F;border=false]" .. + "table[-0.01,0;6.28,4.64;sp_worlds;" .. menu_render_worldlist() .. ";" .. index .. "]" + + if PLATFORM ~= "Android" and PLATFORM ~= "iOS" then + retval = retval .. + "checkbox[6.6,5;cb_server;".. fgettext("Create Server") ..";" .. + dump(core.settings:get_bool("enable_server")) .. "]" + end + if core.settings:get_bool("enable_server") then retval = retval .. - "button[8.5,4.8;3.2,1;play;".. fgettext("Host Game") .. "]" .. - "checkbox[0.25,1.6;cb_server_announce;" .. fgettext("Announce Server") .. ";" .. - dump(core.settings:get_bool("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.settings:get("name")) .. "]" .. - "pwdfield[0.55,4;3.5,0.5;te_passwd;]" + "checkbox[6.6,0.65;cb_server_announce;" .. fgettext("Announce Server") .. ";" .. + dump(core.settings:get_bool("server_announce")) .. "]" .. - local bind_addr = core.settings: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.settings:get("bind_address")) .. "]" .. - "field[2.8,5.2;1.25,0.5;te_serverport;" .. fgettext("Port") .. ";" .. - core.formspec_escape(core.settings:get("port")) .. "]" - else - retval = retval .. - "field[0.55,5.2;3.5,0.5;te_serverport;" .. fgettext("Server Port") .. ";" .. - core.formspec_escape(core.settings:get("port")) .. "]" - end - else - retval = retval .. - "button[8.5,4.8;3.2,1;play;".. fgettext("Play Game") .. "]" + -- Name / Password + "label[6.6,-0.3;" .. fgettext("Name") .. ":" .. "]" .. + "label[9.3,-0.3;" .. fgettext("Password") .. ":" .. "]" .. + "field[6.9,0.6;2.8,0.5;te_playername;;" .. + core.formspec_escape(core.settings:get("name")) .. "]" .. + "pwdfield[9.6,0.6;2.8,0.5;te_passwd;]" end return retval end -local function main_button_handler(this, fields, name, tabdata) - +local function main_button_handler(this, fields, name) assert(name == "local") local world_doubleclick = false if fields["sp_worlds"] ~= nil then - local event = core.explode_textlist_event(fields["sp_worlds"]) - local selected = core.get_textlist_index("sp_worlds") - - menu_worldmt_legacy(selected) + local event = core.explode_table_event(fields["sp_worlds"]) + local selected = core.get_table_index("sp_worlds") if event.type == "DCL" then world_doubleclick = true @@ -186,17 +208,9 @@ local function main_button_handler(this, fields, name, tabdata) end if fields["cb_creative_mode"] then - core.settings:set("creative_mode", fields["cb_creative_mode"]) - local selected = core.get_textlist_index("sp_worlds") - menu_worldmt(selected, "creative_mode", fields["cb_creative_mode"]) - - return true - end - - if fields["cb_enable_damage"] then - core.settings:set("enable_damage", fields["cb_enable_damage"]) - local selected = core.get_textlist_index("sp_worlds") - menu_worldmt(selected, "enable_damage", fields["cb_enable_damage"]) + local creative_mode = core.settings:get_bool("creative_mode") + core.settings:set("creative_mode", tostring(not creative_mode)) + core.settings:set("enable_damage", tostring(creative_mode)) return true end @@ -209,15 +223,17 @@ local function main_button_handler(this, fields, name, tabdata) if fields["cb_server_announce"] then core.settings:set("server_announce", fields["cb_server_announce"]) - local selected = core.get_textlist_index("srv_worlds") + local selected = core.get_table_index("srv_worlds") menu_worldmt(selected, "server_announce", fields["cb_server_announce"]) return true end if fields["play"] ~= nil or world_doubleclick or fields["key_enter"] then - local selected = core.get_textlist_index("sp_worlds") + local selected = core.get_table_index("sp_worlds") gamedata.selected_world = menudata.worldlist:get_raw_index(selected) + core.settings:set("maintab_LAST", "local") + core.settings:set("mainmenu_last_selected_world", gamedata.selected_world) if selected == nil or gamedata.selected_world == 0 then gamedata.errormessage = @@ -238,12 +254,18 @@ local function main_button_handler(this, fields, name, tabdata) gamedata.port = fields["te_serverport"] gamedata.address = "" - core.settings:set("port",gamedata.port) + core.settings:set_bool("auto_connect", false) + if fields["port"] ~= nil then + core.settings:set("port",fields["port"]) + end if fields["te_serveraddr"] ~= nil then core.settings:set("bind_address",fields["te_serveraddr"]) end else gamedata.singleplayer = true + core.settings:set_bool("auto_connect", true) + core.settings:set("connect_time", os.time()) + core.start() end core.start() @@ -260,7 +282,7 @@ local function main_button_handler(this, fields, name, tabdata) end if fields["world_delete"] ~= nil then - local selected = core.get_textlist_index("sp_worlds") + local selected = core.get_table_index("sp_worlds") if selected ~= nil and selected <= menudata.worldlist:size() then local world = menudata.worldlist:get_list()[selected] @@ -268,7 +290,7 @@ local function main_button_handler(this, fields, name, tabdata) 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) + local delete_world_dlg = create_delete_world_dlg(world.name, index, world.gameid) delete_world_dlg:set_parent(this) this:hide() delete_world_dlg:show() @@ -280,7 +302,7 @@ local function main_button_handler(this, fields, name, tabdata) end if fields["world_configure"] ~= nil then - local selected = core.get_textlist_index("sp_worlds") + local selected = core.get_table_index("sp_worlds") if selected ~= nil then local configdialog = create_configure_world_dlg( @@ -298,36 +320,33 @@ local function main_button_handler(this, fields, name, tabdata) end end -local on_change -if enable_gamebar then - function on_change(type, old_tab, new_tab) - if (type == "ENTER") then - local game = current_game() +local function on_change(type, old_tab, new_tab) + 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 - - singleplayer_refresh_gamebar() - ui.find_by_name("game_button_bar"):show() - else - menudata.worldlist:set_filtercriteria(nil) - local gamebar = ui.find_by_name("game_button_bar") - if gamebar then - gamebar:hide() - end - core.set_topleft_text("") - mm_texture.update(new_tab,nil) + if game then + menudata.worldlist:set_filtercriteria(game.id) + core.set_topleft_text("Powered by Minetest Engine") + mm_texture.update("singleplayer",game) end + + singleplayer_refresh_gamebar() + ui.find_by_name("game_button_bar"):show() + else + menudata.worldlist:set_filtercriteria(nil) + local gamebar = ui.find_by_name("game_button_bar") + if gamebar then + gamebar:hide() + end + core.set_topleft_text("") + mm_texture.update(new_tab,nil) end end -------------------------------------------------------------------------------- return { name = "local", - caption = fgettext("Start Game"), + caption = fgettext("Other games"), cbf_formspec = get_formspec, cbf_button_handler = main_button_handler, on_change = on_change diff --git a/builtin/mainmenu/tab_local_default.lua b/builtin/mainmenu/tab_local_default.lua new file mode 100644 index 000000000..e5b3bfb44 --- /dev/null +++ b/builtin/mainmenu/tab_local_default.lua @@ -0,0 +1,237 @@ +--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 3.0 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 lang = core.settings:get("language") +if not lang or lang == "" then lang = os.getenv("LANG") end + +local function get_formspec() + menudata.worldlist:set_filtercriteria("default") + + local index = filterlist.get_current_index(menudata.worldlist, + tonumber(core.settings:get("mainmenu_last_selected_world"))) + if not index or index < 1 then + local selected = core.get_table_index("sp_worlds") + if selected ~= nil and selected < #menudata.worldlist:get_list() then + index = selected + else + index = #menudata.worldlist:get_list() + end + end + + local creative_checkbox = core.settings:get_bool("creative_mode") and + "creative_checkbox" or "blank" + + local creative_bg = "creative_bg.png" + if lang and lang == "ru" then + creative_bg = "creative_bg_" .. lang .. ".png" + end + + local retval = + "image_button[0,4.84;3.31,0.92;" .. + core.formspec_escape(defaulttexturedir .. + "blank.png") .. ";world_delete;;true;false]" .. + "tooltip[world_delete;".. fgettext("Delete") .. "]" .. + "image_button[3.14,4.84;3.3,0.92;" .. + core.formspec_escape(defaulttexturedir .. + "blank.png") .. ";world_create;;true;false]" .. + "tooltip[world_create;".. fgettext("New") .. "]" .. + + "image_button[6.72,1.43;4.96,1.41;" .. + core.formspec_escape(defaulttexturedir .. + "blank.png") .. ";play;;true;false]" .. + "tooltip[play;".. fgettext("Play Game") .. "]" .. + + "image_button[7.2,3.09;4,0.83;" .. + core.formspec_escape(defaulttexturedir) .. creative_bg .. + ";;;true;false]" .. + "image_button[7.2,3.09;4,0.83;" .. + core.formspec_escape(defaulttexturedir) .. creative_checkbox .. + ".png;cb_creative_mode;;true;false]" .. + + "tableoptions[background=#27233F;border=false]" .. + "table[-0.01,0;6.28,4.64;sp_worlds;" .. + menu_render_worldlist() .. + ";" .. index .. "]" + + + if PLATFORM ~= "Android" and PLATFORM ~= "iOS" then + retval = retval .. + "checkbox[6.6,5;cb_server;".. fgettext("Create Server") ..";" .. + dump(core.settings:get_bool("enable_server")) .. "]" + end + + if core.settings:get_bool("enable_server") then + retval = retval .. + "checkbox[6.6,0.65;cb_server_announce;" .. fgettext("Announce Server") .. ";" .. + dump(core.settings:get_bool("server_announce")) .. "]" .. + + -- Name / Password + "label[6.6,-0.3;" .. fgettext("Name") .. ":" .. "]" .. + "label[9.3,-0.3;" .. fgettext("Password") .. ":" .. "]" .. + "field[6.9,0.6;2.8,0.5;te_playername;;" .. + core.formspec_escape(core.settings:get("name")) .. "]" .. + "pwdfield[9.6,0.6;2.8,0.5;te_passwd;]" + end + + return retval +end + +local function main_button_handler(this, fields, name) + assert(name == "local_default") + + local world_doubleclick = false + + if fields["sp_worlds"] ~= nil then + local event = core.explode_table_event(fields["sp_worlds"]) + local selected = core.get_table_index("sp_worlds") + + if event.type == "DCL" then + world_doubleclick = true + end + + if event.type == "CHG" and selected ~= nil then + core.settings:set("mainmenu_last_selected_world", + menudata.worldlist:get_raw_index(selected)) + return true + end + end + + if menu_handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world") then + return true + end + + if fields["cb_creative_mode"] then + local creative_mode = core.settings:get_bool("creative_mode") + core.settings:set("creative_mode", tostring(not creative_mode)) + core.settings:set("enable_damage", tostring(creative_mode)) + + return true + end + + if fields["cb_server"] then + core.settings:set("enable_server", fields["cb_server"]) + + return true + end + + if fields["cb_server_announce"] then + core.settings:set("server_announce", fields["cb_server_announce"]) + local selected = core.get_table_index("srv_worlds") + menu_worldmt(selected, "server_announce", fields["cb_server_announce"]) + + return true + end + + if fields["play"] ~= nil or world_doubleclick or fields["key_enter"] then + local selected = core.get_table_index("sp_worlds") + gamedata.selected_world = menudata.worldlist:get_raw_index(selected) + core.settings:set("maintab_LAST", "local_default") + core.settings:set("mainmenu_last_selected_world", gamedata.selected_world) + + if core.settings:get_bool("enable_server") then + if selected ~= nil and gamedata.selected_world ~= 0 then + gamedata.playername = fields["te_playername"] + gamedata.password = fields["te_passwd"] + gamedata.port = fields["te_serverport"] + gamedata.address = "" + + core.settings:set_bool("auto_connect", false) + if fields["port"] ~= nil then + core.settings:set("port",fields["port"]) + end + if fields["te_serveraddr"] ~= nil then + core.settings:set("bind_address",fields["te_serveraddr"]) + end + + --update last game + local world = menudata.worldlist:get_raw_element(gamedata.selected_world) + if world then + core.settings:set("menu_last_game", "default") + end + + core.start() + else + gamedata.errormessage = + fgettext("No world created or selected!") + end + else + if selected ~= nil and gamedata.selected_world ~= 0 then + gamedata.singleplayer = true + core.settings:set_bool("auto_connect", true) + core.settings:set("connect_time", os.time()) + core.start() + else + gamedata.errormessage = + fgettext("No world created or selected!") + end + return true + end + end + + if fields["world_create"] ~= nil then + core.settings:set("menu_last_game", "default") + local create_world_dlg = create_create_world_default_dlg(true) + create_world_dlg:set_parent(this) + this:hide() + create_world_dlg:show() + return true + end + + if fields["world_delete"] ~= nil then + local selected = core.get_table_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() + end + end + + return true + end + +--[[if fields["world_configure"] ~= nil then + local selected = core.get_table_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() + end + end + + return true + end]] +end + +-------------------------------------------------------------------------------- +return { + name = "local_default", + caption = fgettext("Singleplayer"), + cbf_formspec = get_formspec, + cbf_button_handler = main_button_handler +} diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 7985fd84a..de209753c 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -16,6 +16,10 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- +local password_save = core.settings:get_bool("password_save") +local password_tmp = "" +local mobile_only = PLATFORM == "Android" or PLATFORM == "iOS" + local function get_formspec(tabview, name, tabdata) -- Update the cached supported proto info, -- it may have changed after a change by the settings menu. @@ -31,58 +35,84 @@ local function get_formspec(tabview, name, tabdata) tabdata.search_for = "" end + local esc = core.formspec_escape + + local search_panel + if PLATFORM == "Android" or PLATFORM == "iOS" then + search_panel = + "field[0.2,0.1;5.19,1;te_search;;" .. esc(tabdata.search_for) .. "]" .. + "image_button[4.89,-0.13;0.83,0.83;" .. esc(defaulttexturedir .. "search.png") + .. ";btn_mp_search;;true;false]" .. + "image_button[5.59,-0.13;0.83,0.83;" .. esc(defaulttexturedir .. "refresh.png") + .. ";btn_mp_refresh;;true;false]" .. + "image_button[6.29,-0.13;0.83,0.83;" .. esc(defaulttexturedir .. + (not mobile_only and "online_pc" or "online_mobile") .. ".png") + .. ";btn_mp_mobile;;true;false]" + else + search_panel = + "field[0.2,0.1;5.8,1;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" .. + "image_button[5.5,-0.13;0.83,0.83;" .. core.formspec_escape(defaulttexturedir .. "search.png") + .. ";btn_mp_search;;true;false]" .. + "image_button[6.26,-0.13;0.83,0.83;" .. core.formspec_escape(defaulttexturedir .. "refresh.png") + .. ";btn_mp_refresh;;true;false]" + end + local retval = -- Search - "field[0.15,0.075;5.91,1;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" .. - "button[5.62,-0.25;1.5,1;btn_mp_search;" .. fgettext("Search") .. "]" .. - "image_button[6.97,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "refresh.png") - .. ";btn_mp_refresh;]" .. + search_panel.. -- Address / Port - "label[7.75,-0.25;" .. fgettext("Address / Port") .. "]" .. - "field[8,0.65;3.25,0.5;te_address;;" .. - core.formspec_escape(core.settings:get("address")) .. "]" .. - "field[11.1,0.65;1.4,0.5;te_port;;" .. - core.formspec_escape(core.settings:get("remote_port")) .. "]" .. + "label[7.1,-0.3;" .. fgettext("Address") .. ":" .. "]" .. + "label[10.15,-0.3;" .. fgettext("Port") .. ":" .. "]" .. + "field[7.4,0.6;3.2,0.5;te_address;;" .. + esc(core.settings:get("address")) .. "]" .. + "field[10.45,0.6;1.95,0.5;te_port;;" .. + esc(core.settings:get("remote_port")) .. "]" .. - -- Name / Password - "label[7.75,0.95;" .. fgettext("Name / Password") .. "]" .. - "field[8,1.85;2.9,0.5;te_name;;" .. - core.formspec_escape(core.settings:get("name")) .. "]" .. - "pwdfield[10.73,1.85;1.77,0.5;te_pwd;]" .. + -- Name + "label[7.1,0.85;" .. fgettext("Name") .. ":" .. "]" .. + "label[10.15,0.85;" .. fgettext("Password") .. ":" .. "]" .. + "field[7.4,1.75;3.2,0.5;te_name;;" .. + esc(core.settings:get("name")) .. "]" .. -- Description Background - "box[7.73,2.25;4.25,2.6;#999999]".. + "box[7.1,2.1;4.8,2.65;#999999]" .. -- Connect - "button[9.88,4.9;2.3,1;btn_mp_connect;" .. fgettext("Connect") .. "]" + "image_button[8.8,4.88;3.3,0.9;" .. + esc(defaulttexturedir .. "blank.png") + .. ";btn_mp_connect;;true;false]" .. + "tooltip[btn_mp_connect;".. fgettext("Connect") .. "]" + + local pwd = password_save and esc(core.settings:get("password")) or password_tmp + -- Password + retval = retval .. "pwdfield[10.45,1.8;1.95,0.39;te_pwd;;" .. pwd .. "]" if tabdata.fav_selected and fav_selected then if gamedata.fav then - retval = retval .. "button[7.73,4.9;2.3,1;btn_delete_favorite;" .. - fgettext("Del. Favorite") .. "]" + retval = retval .. "image_button[7.1,4.91;0.83,0.83;" .. esc(defaulttexturedir .. "trash.png") + .. ";btn_delete_favorite;;true;false]" end if fav_selected.description then - retval = retval .. "textarea[8.1,2.3;4.23,2.9;;;" .. - core.formspec_escape((gamedata.serverdescription or ""), true) .. "]" + retval = retval .. "textarea[7.5,2.2;4.8,3;;" .. + esc((gamedata.serverdescription or ""), true) .. ";]" end end --favourites - retval = retval .. "tablecolumns[" .. - image_column(fgettext("Favorite"), "favorite") .. ";" .. - image_column(fgettext("Ping")) .. ",padding=0.25;" .. + retval = retval .. + "tableoptions[background=#27233F;border=false]" .. + "tablecolumns[" .. + image_column(fgettext("Favorite")) .. ",align=center;" .. + image_column(fgettext("Lag")) .. ",padding=0.25;" .. "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;" .. - --~ PvP = Player versus Player - image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. + "text,align=right;" .. -- clients + "text,align=center,padding=0.25;" .. -- "/" + "text,align=right,padding=0.25;" .. -- clients_max + image_column(fgettext("Server mode")) .. ",padding=0.5;" .. "color,span=1;" .. - "text,padding=1]" .. - "table[-0.15,0.6;7.75,5.15;favourites;" + "text,padding=0.5]" .. + "table[-0.09,0.7;6.99,4.93;favourites;" if menudata.search_result then for i = 1, #menudata.search_result do @@ -100,7 +130,8 @@ local function get_formspec(tabview, name, tabdata) retval = retval .. "," end - retval = retval .. render_serverlist_row(server, server.is_favorite) + retval = retval .. render_serverlist_row(server, server.is_favorite, + server.server_id == "multicraft") end elseif #menudata.favorites > 0 then local favs = core.get_favorites("local") @@ -117,9 +148,11 @@ local function get_formspec(tabview, name, tabdata) end end end - retval = retval .. render_serverlist_row(menudata.favorites[1], (#favs > 0)) + retval = retval .. render_serverlist_row(menudata.favorites[1], (#favs > 0), + menudata.favorites[1].server_id == "multicraft") for i = 2, #menudata.favorites do - retval = retval .. "," .. render_serverlist_row(menudata.favorites[i], (i <= #favs)) + retval = retval .. "," .. render_serverlist_row(menudata.favorites[i], + (i <= #favs), menudata.favorites[i].server_id == "multicraft") end end @@ -141,6 +174,14 @@ local function main_button_handler(tabview, fields, name, tabdata) core.settings:set("name", fields.te_name) end + if fields.te_pwd then + if password_save then + core.settings:set("password", fields.te_pwd) + else + password_tmp = fields.te_pwd + end + end + if fields.favourites then local event = core.explode_table_event(fields.favourites) local fav = serverlist[event.row] @@ -235,11 +276,9 @@ local function main_button_handler(tabview, fields, name, tabdata) if not current_favourite then return end core.delete_favorite(current_favourite) - asyncOnlineFavourites() + asyncOnlineFavourites(mobile_only) tabdata.fav_selected = nil - core.settings:set("address", "") - core.settings:set("remote_port", "30000") return true end @@ -305,7 +344,13 @@ local function main_button_handler(tabview, fields, name, tabdata) end if fields.btn_mp_refresh then - asyncOnlineFavourites() + asyncOnlineFavourites(mobile_only) + return true + end + + if fields.btn_mp_mobile then + mobile_only = not mobile_only + asyncOnlineFavourites(mobile_only) return true end @@ -336,6 +381,17 @@ local function main_button_handler(tabview, fields, name, tabdata) gamedata.serverdescription = "" end + local auto_connect = false + for _, server in pairs(serverlist) do + if server.server_id == "multicraft" and server.address == gamedata.address then + auto_connect = true + break + end + end + + core.settings:set_bool("auto_connect", auto_connect) + core.settings:set("connect_time", os.time()) + core.settings:set("maintab_LAST", "online") core.settings:set("address", fields.te_address) core.settings:set("remote_port", fields.te_port) @@ -347,13 +403,13 @@ end local function on_change(type, old_tab, new_tab) if type == "LEAVE" then return end - asyncOnlineFavourites() + asyncOnlineFavourites(mobile_only) end -------------------------------------------------------------------------------- return { name = "online", - caption = fgettext("Join Game"), + caption = fgettext("Multiplayer"), cbf_formspec = get_formspec, cbf_button_handler = main_button_handler, on_change = on_change diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index 1e5264904..59e80739b 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -122,56 +122,6 @@ local function antialiasing_fname_to_name(fname) return 0 end -local function dlg_confirm_reset_formspec(data) - return "size[8,3]" .. - "label[1,1;" .. fgettext("Are you sure to reset your singleplayer world?") .. "]" .. - "button[1,2;2.6,0.5;dlg_reset_singleplayer_confirm;" .. fgettext("Yes") .. "]" .. - "button[4,2;2.8,0.5;dlg_reset_singleplayer_cancel;" .. fgettext("No") .. "]" -end - -local function dlg_confirm_reset_btnhandler(this, fields, dialogdata) - - if fields["dlg_reset_singleplayer_confirm"] ~= nil then - local worldlist = core.get_worlds() - local found_singleplayerworld = false - - for i = 1, #worldlist do - if worldlist[i].name == "singleplayerworld" then - found_singleplayerworld = true - gamedata.worldindex = i - end - end - - if found_singleplayerworld then - core.delete_world(gamedata.worldindex) - end - - core.create_world("singleplayerworld", 1) - worldlist = core.get_worlds() - - for i = 1, #worldlist do - if worldlist[i].name == "singleplayerworld" then - gamedata.worldindex = i - end - end - end - - 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() -end - local function formspec(tabview, name, tabdata) local tab_string = "box[0,0;3.75,4.5;#999999]" .. @@ -218,16 +168,9 @@ local function formspec(tabview, name, tabdata) fgettext("Shaders (unavailable)")) .. "]" end - if core.settings:get("main_menu_style") == "simple" then - -- 'Reset singleplayer world' only functions with simple menu - tab_string = tab_string .. - "button[8,4.75;3.95,1;btn_reset_singleplayer;" - .. fgettext("Reset singleplayer world") .. "]" - else - tab_string = tab_string .. + tab_string = tab_string .. "button[8,4.75;3.95,1;btn_change_keys;" .. fgettext("Change Keys") .. "]" - end tab_string = tab_string .. "button[0,4.75;3.95,1;btn_advanced_settings;" @@ -359,10 +302,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) core.settings: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 diff --git a/builtin/mainmenu/tab_simple_main.lua b/builtin/mainmenu/tab_simple_main.lua deleted file mode 100644 index 7ec95158a..000000000 --- a/builtin/mainmenu/tab_simple_main.lua +++ /dev/null @@ -1,220 +0,0 @@ ---Minetest ---Copyright (C) 2013 sapier --- ---This program is free software; you can redistribute it and/or modify ---it under the terms of the GNU Lesser General Public License as published by ---the Free Software Foundation; either version 2.1 of the License, or ---(at your option) any later version. --- ---This program is distributed in the hope that it will be useful, ---but WITHOUT ANY WARRANTY; without even the implied warranty of ---MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ---GNU Lesser General Public License for more details. --- ---You should have received a copy of the GNU Lesser General Public License along ---with this program; if not, write to the Free Software Foundation, Inc., ---51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - --------------------------------------------------------------------------------- -local function get_formspec(tabview, name, tabdata) - -- Update the cached supported proto info, - -- it may have changed after a change by the settings menu. - common_update_cached_supp_proto() - local fav_selected = menudata.favorites[tabdata.fav_selected] - - local retval = - "label[9.5,0;".. fgettext("Name / Password") .. "]" .. - "field[0.25,3.35;5.5,0.5;te_address;;" .. - core.formspec_escape(core.settings:get("address")) .."]" .. - "field[5.75,3.35;2.25,0.5;te_port;;" .. - core.formspec_escape(core.settings:get("remote_port")) .."]" .. - "button[10,2.6;2,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" .. - "field[9.8,1;2.6,0.5;te_name;;" .. - core.formspec_escape(core.settings:get("name")) .."]" .. - "pwdfield[9.8,2;2.6,0.5;te_pwd;]" - - - if tabdata.fav_selected and fav_selected then - if gamedata.fav then - retval = retval .. "button[7.7,2.6;2.3,1.5;btn_delete_favorite;" .. - fgettext("Del. Favorite") .. "]" - end - end - - retval = retval .. "tablecolumns[" .. - image_column(fgettext("Favorite"), "favorite") .. ";" .. - image_column(fgettext("Ping"), "") .. ",padding=0.25;" .. - "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 - "table[-0.05,0;9.2,2.75;favourites;" - - if #menudata.favorites > 0 then - local favs = core.get_favorites("local") - if #favs > 0 then - for i = 1, #favs do - for j = 1, #menudata.favorites do - if menudata.favorites[j].address == favs[i].address and - menudata.favorites[j].port == favs[i].port then - table.insert(menudata.favorites, i, - table.remove(menudata.favorites, j)) - end - end - if favs[i].address ~= menudata.favorites[i].address then - table.insert(menudata.favorites, i, favs[i]) - end - end - end - retval = retval .. render_serverlist_row(menudata.favorites[1], (#favs > 0)) - for i = 2, #menudata.favorites do - retval = retval .. "," .. render_serverlist_row(menudata.favorites[i], (i <= #favs)) - end - end - - if tabdata.fav_selected 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.settings:get_bool("creative_mode")) .. "]".. - "checkbox[8.0,4.4;cb_damage;".. fgettext("Enable Damage") .. ";" .. - dump(core.settings:get_bool("enable_damage")) .. "]" - -- buttons - retval = retval .. - "button[0,3.7;8,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]" .. - "button[0,4.5;8,1.5;btn_config_sp_world;" .. fgettext("Config mods") .. "]" - - return retval -end - --------------------------------------------------------------------------------- -local function main_button_handler(tabview, fields, name, tabdata) - if fields.btn_start_singleplayer then - gamedata.selected_world = gamedata.worldindex - gamedata.singleplayer = true - core.start() - return true - end - - if fields.favourites then - local event = core.explode_table_event(fields.favourites) - if event.type == "CHG" then - if event.row <= #menudata.favorites then - gamedata.fav = false - local favs = core.get_favorites("local") - local fav = menudata.favorites[event.row] - local address = fav.address - local port = fav.port - gamedata.serverdescription = fav.description - - for i = 1, #favs do - if fav.address == favs[i].address and - fav.port == favs[i].port then - gamedata.fav = true - end - end - - if address and port then - core.settings:set("address", address) - core.settings:set("remote_port", port) - end - tabdata.fav_selected = event.row - end - return true - end - end - - if fields.btn_delete_favorite then - local current_favourite = core.get_table_index("favourites") - if not current_favourite then return end - - core.delete_favorite(current_favourite) - asyncOnlineFavourites() - tabdata.fav_selected = nil - - core.settings:set("address", "") - core.settings:set("remote_port", "30000") - return true - end - - if fields.cb_creative then - core.settings:set("creative_mode", fields.cb_creative) - return true - end - - if fields.cb_damage then - core.settings:set("enable_damage", fields.cb_damage) - return true - end - - if fields.btn_mp_connect or fields.key_enter 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 and fav_idx <= #menudata.favorites and - menudata.favorites[fav_idx].address == fields.te_address and - menudata.favorites[fav_idx].port == fields.te_port then - local fav = menudata.favorites[fav_idx] - gamedata.servername = fav.name - gamedata.serverdescription = fav.description - - if menudata.favorites_is_public and - not is_server_protocol_compat_or_error( - fav.proto_min, fav.proto_max) then - return true - end - else - gamedata.servername = "" - gamedata.serverdescription = "" - end - - gamedata.selected_world = 0 - - core.settings:set("address", fields.te_address) - core.settings:set("remote_port", fields.te_port) - - core.start() - return true - end - - if fields.btn_config_sp_world then - local configdialog = create_configure_world_dlg(1) - if configdialog then - configdialog:set_parent(tabview) - tabview:hide() - configdialog:show() - end - return true - end -end - --------------------------------------------------------------------------------- -local function on_activate(type,old_tab,new_tab) - if type == "LEAVE" then return end - asyncOnlineFavourites() -end - --------------------------------------------------------------------------------- -return { - name = "main", - caption = fgettext("Main"), - cbf_formspec = get_formspec, - cbf_button_handler = main_button_handler, - on_change = on_activate -} diff --git a/builtin/mainmenu/textures.lua b/builtin/mainmenu/textures.lua index a3acbbdec..74070840c 100644 --- a/builtin/mainmenu/textures.lua +++ b/builtin/mainmenu/textures.lua @@ -3,7 +3,7 @@ -- --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 +--the Free Software Foundation; either version 3.0 of the License, or --(at your option) any later version. -- --This program is distributed in the hope that it will be useful, @@ -46,12 +46,6 @@ 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") @@ -60,13 +54,7 @@ function mm_texture.reset() mm_texture.set_generic("footer") mm_texture.set_generic("header") - if not have_bg then - if core.settings:get_bool("menu_clouds") then - core.set_clouds(true) - else - mm_texture.set_dirt_bg() - end - end + mm_texture.set_dirt_bg() end -------------------------------------------------------------------------------- @@ -87,7 +75,6 @@ function mm_texture.update_game(gamedetails) core.set_clouds(false) if not have_bg then - if core.settings:get_bool("menu_clouds") then core.set_clouds(true) else @@ -172,14 +159,5 @@ function mm_texture.set_game(identifier, gamedetails) 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 universal fallback texture in textures/base/pack - local minimalpath = defaulttexturedir .. "menu_bg.png" - core.set_background("background", minimalpath, true, 128) + core.set_background("background", defaulttexturedir .. "bg.png", true, 256) end diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index d077e4065..c787aea2c 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -975,7 +975,7 @@ enable_remote_media_server (Connect to external media server) bool true # Enable Lua modding support on client. # This support is experimental and API can change. -enable_client_modding (Client modding) bool true +enable_client_modding (Client modding) bool false # URL to the server list displayed in the Multiplayer Tab. serverlist_url (Serverlist URL) string servers.minetest.net @@ -1124,7 +1124,7 @@ player_transfer_distance (Player transfer distance) int 0 enable_pvp (Player versus player) bool true # Enable mod channels support. -enable_mod_channels (Mod channels) bool true +enable_mod_channels (Mod channels) bool false # If this is set, players will always (re)spawn at the given position. static_spawnpoint (Static spawnpoint) string @@ -1315,7 +1315,7 @@ server_side_occlusion_culling (Server side occlusion culling) bool true # LOOKUP_NODES_LIMIT: 16 (limits get_node call client-side to # csm_restriction_noderange) # READ_PLAYERINFO: 32 (disable get_player_names call client-side) -csm_restriction_flags (Client side modding restrictions) int 60 +csm_restriction_flags (Client side modding restrictions) int 62 # If the CSM restriction for node range is enabled, get_node calls are limited # to this distance from the player to the node. diff --git a/textures/base/pack/bg.png b/textures/base/pack/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..55afbb6f4e16ee5f4d9c8b9483a909457b9c3c3d GIT binary patch literal 8482 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 Q(EtDd07*qoM6N<$g3nJ^$^ZZW literal 0 HcmV?d00001 diff --git a/textures/base/pack/bg_common.png b/textures/base/pack/bg_common.png new file mode 100644 index 0000000000000000000000000000000000000000..6384c06cc3216d01bbaed6707b4dbbd41f69384e GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uDsl0NA7&;-+9j~tVYsn zdMZ#n(9^{+q=GS7f!UyK5d*spQ{?Ii2fQA!{QKWjc>Vuz#fA%w&I~J<*ReY@9FCIW z=;7+&67Xwn2{w9o$Ki(T*Z&g_#4k8dFY@5PfgY`bhQ<;Gh6VMSRvTAs-w!mL!PC{x JWt~$(695}|H_-q9 literal 0 HcmV?d00001 diff --git a/textures/base/pack/bg_local.png b/textures/base/pack/bg_local.png new file mode 100644 index 0000000000000000000000000000000000000000..2ede21741fc7dda13c3839911d160f9998f50c18 GIT binary patch literal 4805 zcmd^Bc~p~E7Jr|SMHJe~Dv5Sf6a@h-2NDojW)uol76p+G(pUy?RF;qeGGPfK;0z`z zn~HkC1BeW=IIe(_R4OQfn1T>MffzRy0Z|fU%eu`GsD=SRxTQ*f8j{`e5GbhbTRpcx>9RBChbJQj<~}cC611gz`&Y$^CX84gJ|U|?=Sz!zWF^g$G+R{x&zq1K~Fna))uL7tw9=0RzwTBrGN!%m?u!l%O8(hdu z(P{XmAfPSo;tv$5Ck6362GAQ6sv2_y@(h);@A)-f$JP4J8K|;9LMsDW0UsQ#-wR9% z)rTqL)&EVA0Nen+E{(?abOHafnFOdc7(XNf3{|gegv~MhrIM7mmLx#5J!2}lEdbpo zU*5sM!Tfnr3!(;7J=0(lr=8AyCq7>VslKd8N_TEDfhvp&%g|-84XJHc`>QCv^8O%d zaOwN0&nL*Ubj-!n4-CO9=b-5!L!n7~7@-s}$uU7Hyi>~sVAz&z8&ijw%9~YP1qAGo zYVbM0gqlcF5A=<SRiI9NOUn1A+xMYQUq&9Cg$I z3Mdzj{m|)9d?T?^KA>P3WKrW04!@P=Wg+}<6lM?LbD-edWMOHdZ62C;3ssm)Rc^}1 z4>Uizp=7*mF$y2*?W-mYiwmb(aN9Vu`SIx(3JJM~8BDq!;WSF!x+lu~ae3QPV)|Dh zpZJ`GK1IY$$RQpRL^dpcO1bfj)9zVtxK?%pm@z&LQN|Oj>;RKF;q5Ye?=hi12Z?S3 zBz&0aS2ZO*!4o-JGRVP%x&q`7v*a`HF7iVaf`KJm&zw?52`a{mPRNPiPA7NHH99Vy zqoH!<5X^4mqRQ;s9s4kONfCYwX(GN9rjYKjCP6rS8_x?N1*2^$P8hs%`Qz$=kmRl^ zsxXcu-3s9F;-}htDUpPk%>hyE;$RsLL&DiUhMrMRD}J=I+Lu5hK-&hkjPFw&@fTp1(^%jzdPOTHUtx=Owx zao)-W$`QWdq?j#m=I|r9f}ImE|n|r6a@0jNe{GczU&D4Z9{@H}SA$ zr8vGZ?U4S~)2dm`(N9{u2DCDU(v#ITU0-cd91>^sZW$eObGA%K4F+0p8z;cM3un{V zk)>>>LLKF4=S(Br^3$;=3GQ$zk>H~O4{6j1%?dNEV3yD7 z+WJmKp`K>mrUXt@!zF;gO3LeB@}kybkQglT3B0wtbpMDU^^B|KT{na?)6JVQUQ3HC zp!xO^d&g@{0MgnE_yzadV*2&#dR>I~GOIlzVuk$=mQMSor|y^)CUaY6^SxB8ymxB8~Hk9m0VmagrEvC**%(W$k;JFc&_;|W=A z7`ngZeyjz1&*OVlK+KrRpQ*p^b{}>PTvt5Ni(qfm=*3s)NB8+15j-=cbAFIiv=KXcokv*{e>iFq#%BUQ)W)@?$s7-thJ)FvDgbQ$;)cq zxubESp!`<`6N4Mu9`_IJCCR8$*C=8MdS6>j7<`i+^Pt`6n*o|uc~eCHopm@5JIP-R z5Y5WE{klrh{;FTslYL>mc}s)2mu1a4+hv`Lf=g`*zU$-=T}P#~8IPN&HFbW+uEjq2 z&?V{9lCkF01NzRp)wJuzmh4yS%>B&61CxuQ9+CxF2OML+Xbl{QKzG^4PBgjiZPprh zETRo;53;KaqoxX%uowt_ZyEWm7KFQNN)PXTZFthkpk3n7&Gb*(f&;X3D$=ncbP*8|tZp#k zGu(hf`!3c$+xhjS5j9!CI}An}SpMX<2J6eFo1`QtuiU@Z6hN60MB$gZu@)!9;lgd7GfsL|X6vGm$BBBv7c^4|t4>KRhb(Ok# n=p}KoB;|6U^y|!Tzd-t7aeaJl($2z_$k=&{>*mrwQV;zb#S%73 literal 0 HcmV?d00001 diff --git a/textures/base/pack/bg_online.png b/textures/base/pack/bg_online.png new file mode 100644 index 0000000000000000000000000000000000000000..864cc522710f33187307deffdc46d87e7492cee5 GIT binary patch literal 2676 zcmeAS@N?(olHy`uVBq!ia0y~y;3!~VVBW*R3>3L}{!BiQQVH-0aRt&|VKqnYd{Qxv z3{IVs*LKXtr|ROxi~s-sZ*FdW@ZdpQT-DzG6*jS}*kY(po_=K{Kn|^yi-+^6S>u zo;*E0{#d3t&^Us?B(;KL>m$7@ECPHE77Py=pi~R903VPCqQJr}%uouj9jk{dmnfNbyu6Bv*Ud^c_uM-1sR4zj2u9!p#aE$QXoFE zFb6wW7OD)c8mBO-ZXAXp2?I?ZAVZP;h12^;E+sish%_{Z`sroRC3u|K1=*$4O7JN8 z9m!B+yND_Vh{>7^4{snR3>@hNNtmbvPxG{il;?=bu{iTPvP(%dl-8j#go66_VdMgs zGKV|Ni88zAVZqQ1uJaE3JobBG>i650?rR@1=s+sLN0)!HeZL&x2~pEf&iG^Vy7w-+#gYLSB3 zoBuD#f07>BkoVz@82g@i>%OlFl2MR(AYbb357g1Z{6cGn45+G^A#)X!@eVuz<;nw3 zIxgquwlZ(9U|0^7t&?ZpAmh}LJj3sPgiL|54_GsZd{ko8#(h~|y#Do{v$MI`6N*4d z4MaX*lDP2o^UM7o^dD7J`kr~ja8KqT*f@*FK&tRoZTOmx1q_-oiJpn8-9D|_#Qft) z705+9stYW*{)AWOm)OoPQt4*q;ajie;MxMD(`6jy==4oXDA;r4{AMnYH3e%n7chtl z@EKT4n{sL4GLWYqv^ay>7|qIl=iMGM#8|fPFSf0j%RRp!0#uo*vbBecCU}PbUEgi* zEygY(6BpW`&B6ZRafMBto~;F_ykGEITORCb2{0+JeB+-7pg?JO#oi98joH9t&HoQD z@zOkHnFF)Z&%X<2-^cgl_-ZboJ*kHn?|rc?FNH-4!?Z7&&uz@BPi@RQKkxJP5&=GN zt-s>e9 z-`YJQWmp@-r_PZt|8=u3R)m3r#ew0DQpSHT50QU6?&dE$!gVLGzgVb7hQU_kN*Z@B dsGW!tG_b}5GdOPf80Q00;_2$=vd$@?2>=&6+@b&g literal 0 HcmV?d00001 diff --git a/textures/base/pack/btn_play.png b/textures/base/pack/btn_play.png new file mode 100644 index 0000000000000000000000000000000000000000..aa8f828229b65f23f9e09bc902f8a0d2d0a22a14 GIT binary patch literal 677 zcmeAS@N?(olHy`uVBq!ia0y~yV739WkFhWV$)}bx?17YAfKP}k14E*Uab$4noV>PU zHa=AsFJAor|9^9H^MeNu;^N}+=5nS2RWgEakt!T9#ZLEk41 z0&N#P6N7Jv%wf`;&=fpF#G^4sGQ>p4$SxxF)Y@6!W&bH-w?&z~ou5PQGiK(l*=)Mu7+$`+eNgcw`c`#+dGZ#4Gx zKL`~6;4`fcsQ<%*%Aa|H^A>&J;Foi#cy(CWrXo(B@ldd|+{1&+9R8&hE$sXXHdh}C z%Gor02x$lEo5Q!|pWHkkzv9CKPlksFC-dwhuDu(dK7ADngVuv->OARPX^c0$D~j6_Xq)=N*aW1sVnt5aT%i5yFzoxEpfZ zIO{0T6eFv->bu<7_~-r2ssu~&&-?usXivolo$9&gg|A+IaBy>bGdsu`A3{E|_;G_6 zJs%#-oR|IpWa{~wKvy0BGWh2KLr0}RrW9z(WDfp$Hhl9AgWSPCkJpd!{I+W#FCA=t z{?@%x2E?=k+5u#_9|8r}frG)qz%bcd$I9-X3knq(o2{TwDfkf529(}o-_*R^&gM`v zJKwxppun`K&;kXfl0`)qh<@DNm!}}%CXdY`Cb^YBW9ISS{QcC;`^b4-U}|FU MboFyt=akR{0QvAEy#N3J literal 0 HcmV?d00001 diff --git a/textures/base/pack/creative_bg.png b/textures/base/pack/creative_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..7f269f655374fa41600fd0c5657601223745a5fb GIT binary patch literal 418 zcmeAS@N?(olHy`uVBq!ia0y~yV9Efpi&&U}q^PjLIv~X#;1l8sqzz1M4jw%C|NsBs z)HyZDTADy1#*!evU`pt{Ol%vJE|q&sQtF2nJbr``NS&HshMppXVkkXNB@CTHGj*U zQuNVe^ID0N8JD|Vx7zl;F4&@f^F9+u=OrDrqZy31c=dNmN^SWy*KD@Y{J(*bOXYOa zzbppYZjzDiF#Gt9nzatiY(N`w_Q*%^tnmck6>2`11+y95uCNa@pA`f u#s!wMiw^*us@9*=%Emhj5(p|QUvYc!7d99zDEJEuSq4v6KbLh*2~7ZxhOaFE literal 0 HcmV?d00001 diff --git a/textures/base/pack/creative_bg_ru.png b/textures/base/pack/creative_bg_ru.png new file mode 100644 index 0000000000000000000000000000000000000000..7a32cd79291652dcb4ade7a4a65be3ed7fd5634c GIT binary patch literal 5351 zcmcgv2T+q)*A7kT9adZxLltC`kOWAGp@yn-=`3gn0YXa*k%W#QQbbSz70`tM3&8?P z6Ql`ZK@p=O2r5XICLmSn_hS3@pV|3l{(rvtGxO%$d)`x?bM84OH_5ivWBB!`WKka9~?1*@qNJ1cA&SUA;(maOjaveBMY8 zXFk(-DHEOn)reh$f`8+-+vBrq&lAvnL94(dmVvRD7>CKZ{8)}crumH|FL_ngF%ff7 zTQ7|i7R%eT`%q+9*zD-&%A>}CKHu4pmEMTFYA8s_W*-#BbCDCAz5m1RaP%wZ1T*&S zP0%hzEJra&!*!yx$?#K)ff5Y$OZeT#d>d!_1v$(&nus4KY)ay{ZC>7RXaa#AA8i{8 zw8k86`=Vg|M6xJl2B}c|P$@;mG&vh~$hM8@mF7P3S6-BKuU*Hqx14+1(3K;-?Sb%> zBu2#PbBbPVW^Ft&e^?hMkWYed7V3`AbKZp>P7n4EdX^tSMP#5kPcrp0vL26APC(V#OD#RM zL1%ooewR5OG*O`7p5x~3wl_y6JKB!5eRmb5{Aos^k$?3aGO2qdai)C3eiC%7BgMaR zO2oY*8ic9g1k<-ga>wLBN+wYO&GQe!{D#7kf8n(cN$hcl?fhdP~nC-izf%UO? z5uTykUy3oe(JOg8o9kti*ry*b zwS1pqcOTUjaW!Lz< zFLTzloMrLpEi-dGtC+~$awqfdSMnMp@e0}D1jTj@#jVPVng8BurVUOo*RfBm0(+Rl zr~)#E#pmg&f+=wYg@Sf9sx}V1DG7&gK?YKV2kgx3W>|7vkSO0BjFJXHACgUWnW^`*~1@EdjwCPe$nEB$HE6Mb9Z1Y;bWj;sSr72tjzrmuiGwR zH#oY5rxJ-?Ja0Isqo?81I@91#*>!2Nw$h;v%BNahS&>VL>W{PrJBM~1m#7VEkn|KF z$FJP4obO!~kJN1vh~d&t%iC`*LE{ZQb-0h_H&CC&?55-=c+Pjr)YoD(ic-KRRS`8YZvq82-{zGKJxs=jRpm5cBBXL-%@`O^I6T+ zNf(*5*(KvD(@U&iR=8F;R``0G`SDuij+q=T$YNWwPy5YYQiUCNYjv$4SUkPZq8vg^ zp{7w~>x}B0>JCz8M<+f9e@^~fKYDOvpIW};q7iVpN0sE`zpvQh1K zj>}ri;>_w+`^{^3-yn>i!xfuS~gltx0`OweGPZh!jr=P48OjnC=|B~r|48@S?EqMJ>vMv8R=Z< zy3i!;d4?%fUTt&TIl$W8?4V^tZfN3iQQDQXOV(-Dm7O?`in93NoZzdUf^<{ma4@^s z*nX=hmjNSv&*nqhr#S+Tk?v`sk7?YJZ0rhGBa`00#N#e7Gw`SJm4hs?XOADLK4;zk zm~gxJ_^J8eVb5V36=@X@ELd@n$zbC0a5su*#vaj|wKxtX{-x(gv$f-$D>;S{aDzTWV{CDIgK`=T~y zu7q~;o4tK1ecHX&&>q)LSI_3i4(s=6Bm(88@8hvm5q5QFXG*$>>h&A{)G>~$I z@-pNQ1v9qT+S`^r`)&+7?loM|KiZ%^G&$(@v2RvoSbE55V)>27d)>~)-l&K7TM1Vm zh1pb<+!+skj)xIp7o7`xI{2?kO*t)SM<;Qv-Dil_V}H)g`&8@auKN+`=bNX5vUO%py7oU(OqkSvviAW(lQX92w>w9qV zq4mSw2Q$gJDfA>*dfwPwih3PP0xRJ!J|?~?o~{H{N>Hv=8NN`MVKeW|NN)I3GAr{& z=1GV6uDGuAnz>btBxEEx8i&bjQfWM5Ahl_^#CIaWJ)ux$S;kR@jKm>rd@OwDE7mHO zD(T)fBemm^jl$Jw)nx~rA@q<>AHz$Qs(;NFg8zCKbg6hsN+ zmZX`;)qgoVg}Mqk4XM6a)m}Syl3dvQ8)h)7U|nh0`zhUR!10bzJ=EFyXmwrqT(Nx9=bp6vvV^IWb*7sdr z%&iIeHT9JYw2JDP%X6Hy?ghzx3@h*N`Y;Sa6uVBcG2vuj{wZ=ZBS)%Q8U2dqnNvffI!0c zcOH&MWR^Dw#Kj~zxX@gzEHMOf5ESoC_98+VK@>n5xToqfD0o5ukp}i6`jUcm6=v(3 z6~H8KT?JbV-eJQOz+XjZ0lEr?J08IXqnMwp}LA4fP{nv)9?&PaERhJBj3#!6GI485`{)02ZMLa;=RZxXu1jj;%}h@QLLm_0Fse1b|K0^*84lz|-n zXGc4N02+)9l?0p)KG2v2h5G_??Lt1wMdJ+7ni?h=hH$uv5gMVTVXUdGp=F5EF-5^Oe&|{R zhtTlB1mX|hB*6D~UF3h%#o(w!JdI3sAd>@sRD-P_nMMxrBU8Y@-y-1jb-=1tcmgSS zhpG1Cw1D&a7QQi&N(v=U~11-RH{d^WM|@r42~f%DJI|=*y4~%wBQ1 z9LV7Rg`}TeUgwHzyD`rW-WI% zbp3rF6oV*{S(~j`P4`w@r7}Rg!u_Vl#YBQSk8XqaDCKqHBDew%@nWldu~j;MUqn|k zH#;7CVrwG4a>ub%-xr_Rt5ZTjtrEjf|G0uvMs*ee%pT{xgZotw-&7r=N!Xg!%)qyUg7h$nGWTdD%U+r9Lr!!(paH%xsN{sAM7e6H@N4 ztX8!p{wqcl13O!kvBdzkp0lJYz)Y3e{wwz7zcEEM<#HBRf&(}W;cH`h!**_J0Q;UA_ijm^6S&O9XO-#ziqKO=Y=+-| z6Wp_0;j>_6EbnOi^0?l!cv}?*`*NX^BkCQCG6|wrqMLxAdS*YXIyva$*(1oe8&^38P+dnXVIw5eW6_Am9L}`W$g

)OLM9>C9UhCFPXJFpXebE-TXzw>d!l74m{POg3or4()iL}em4>6 zNZ(ZH4-b3ABu3T0*BLZag=I`P@D-9V1&3G$Xw4l=Y-Ox)bq{P{PgFqG`sTGS0HkrN zJyEa39F2HdnO_5g4jyMUMt^zu(f#_nS?6a*v6?#M){nVqEb#-P!ascCW|p3!Ob6UX zqnrJ=faHWpm=4g4vusaN{EDBep2|PWko7M=+5}(gKCrUxxNzy{m_C=(U$S}E>&XQd z!h?8Ee+z$`=k=F*XXg{kpm6!Uy$982);MxMcylirMCa0OjmE<@z2C{tw0_oPa*E#!*pVVYrVSxrjxIs0vV?#!fj!jLu>&bQgEW>`eP z-=?R(A1u(9e;@pByrCEDjxETyf&6_g|F4Mj>ijVI1Q*BU72OLjckXx=Cf3GfM#tj* E1u1cSMgRZ+ literal 0 HcmV?d00001 diff --git a/textures/base/pack/creative_checkbox.png b/textures/base/pack/creative_checkbox.png new file mode 100644 index 0000000000000000000000000000000000000000..afc0933fe6366b573b535e0db4c2345e457bd06e GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0y~yV9Efpi

! zEI$JUoK-Q|vMnQi*}{bj-==0{yzOdhyT<*aAR{BwT-(9fdpA&gskfxmEd`S;K0x{A o3m2N&o{2TIA%kzxv$nissR~x$5W5(-59kmEPgg&ebxsLQ0EMMa>;M1& literal 0 HcmV?d00001 diff --git a/textures/base/pack/logo.png b/textures/base/pack/logo.png deleted file mode 100644 index 48793678f178139f0713f0a4aada1e9736b78654..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12188 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 literal 0 HcmV?d00001 diff --git a/textures/base/pack/online_pc.png b/textures/base/pack/online_pc.png new file mode 100644 index 0000000000000000000000000000000000000000..6f42d2f173e4667524f31e6678bc6220c60ca566 GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-u0UGFI5IeO&j0`atEHc< z1o9b6g8YIR9G=}s19ECTT^vIy7~fuDWMeiIaC_)3!nO0lC2bKV+t`H@f}eO4H%t<{ zX?pmGh~@_V4~#a?gPd OVeoYIb6Mw<&;$V05KQL) literal 0 HcmV?d00001 diff --git a/textures/base/pack/refresh.png b/textures/base/pack/refresh.png index 7193677b43bea725df64fc6c84de9546787c1ffd..8e0d28d21e39b6e033954c2ec18f2d45f7a5a301 100644 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uK)l4S22zZPMrf}Y^%Fm z1Qcg13GxeOaCmkj4anK)>Eakt!MNliW16d>K%8*R2cKvHHZMO${He zOB{2I`*@H4hs;5jOR1jhJMvyz9XPK0`k&Q-{=?51_dR|2y_92y)apcr+lma!7;jdY z@NAOhGYb80bG a3=E5zRJTu(-aZxR2?kGBKbLh*2~7Y4Sa6d7 literal 3660 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 DZQC6y diff --git a/textures/base/pack/search.png b/textures/base/pack/search.png new file mode 100644 index 0000000000000000000000000000000000000000..200cb19ec30df124dd2ce675a00a7388c0e35744 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSoB=)|uK)l4my?qNk{YT{Ujqdh zOM?7@862M7NCR@FdAc};RK#7qvXPhBkfSy6bdZ!=;w+KrwKiO;zm}i5Yx?k^RZ!ED zXW2cKhaNBe`lg^Ktp7f{vIqks^P(o^$VQvB2U236Gf!JyCDP%|{ew3$VXgsp0W)jf zKeHEGtCOo=|9<@K`FF-jdBqnK)H8UFU0N_lOm$_Vzth18u5$qjqG}5hbXe0hCde*2 l{OW@|_m%Sc|FTtk8TXxwvMD=%s|V;p22WQ%mvv4FO#p#7UV;Ds literal 0 HcmV?d00001 diff --git a/textures/base/pack/server_flags_creative.png b/textures/base/pack/server_flags_creative.png index fa37a19ca6730ccceef243b1b38ed954d0622e70..e76455489fe045dd0b59b436acde71a8f88cbf7b 100644 GIT binary patch delta 236 zcmVis(=6h00DGTPE!Ct=GbNc004tYL_t(|UNwtZ76UN| z!?4YgWR~{+r!AdDUr5i`#kK*Yy=<|n<|Og>TBE+7&pF7~M`aJrTEpWX+7AcLI%-9G z)yM=O9W}c2hr57GNmqy>(d?bv!|1mI)V~!JOXA347_g>m@&UuLJ~;1Z*|{0000F@9^;U_@Tzq zH)VB8eU9tz@luDGgrcqN@bc~Q^HYeK?(_9~n4v*&f$Q_7$^ZZW1$0tQQvh7Q=J`SQ z5mW#G0C`D7K~#8NWslbi!!Qg*-Nc$6S?&M-YBdO zp@&KY7mzA2MW{l*H%wT>ADJfd!d2oe+O~@z4(7LuhTC8j9=m6uiH#YEtTntO v2D?QksWGb_{^Ss?>npcW5h1Fp@!$GiT*d}}U5Y)d00000NkvXXu0mjfjWBxi diff --git a/textures/base/pack/server_flags_damage.png b/textures/base/pack/server_flags_damage.png index 3f0bf0daf5c1d43bf4d1e16b3eda18d87b8be7cb..97e450a65674e2089ee7cba40f227eb21a37ff76 100644 GIT binary patch delta 186 zcmV;r07d`F1=RtNBYyy#Nkl7Mc=~0{@(&nMh6xE!%z^07f8m)dRaOfR4G7R)j9He1dmAif337NzfEh6_6gbI zt9Q@(M`zERMhMWMfdWB5W1WF-?Kpw$D-u~Tx(7Xzu>o!7T{GNcP>g?}LKGG;0D(}< oK!F^@jGV-boX78QWgc1q0B&UwhP-$uzW@LL07*qoM6N<$f*<)(4gdfE delta 690 zcmV;j0!{tZ0m%iBBYy&rNkleC{lFA|eERxqINNQ1I2{FF z9B#KhYf5>xE!^FP)>)qj6(?_PX${q7BMrav)!>&VQ_;Lwa@dH}u;j)QOt^zO*nLGS%$x8oB9U>z_9v<6+!D2+t8Ej$k_po?)%6RKjaZ_3wX zS9kS)8N?~XDK^W5eEjduFTe+Q9=HyaRZa3Fgdu1Hj;%$Nf-HwPL+!?>(daLE|Iw3M zCv&yjafOR;K)CfHgPY~=)h)t+kru=E9DhC5woe~xG7)5;v@*J`;IY}`|#yzdCovy0S z0mD-W)*WXx6C$_1Z*3G>+l;IY18WdL_t(|0b;-h{x6gM|L=^}e|&0aVgN$(4|T8sAU4?s{CJ`W zHh^T!|6e-84fuIg0niv(TOkmHK^S-U5b1-yNT~vs7;=b+Xany7hvm)x800+oPIhF? zyaa+4hFS1iqQ!+hGN6TF?YKJB1!S>;IA=YtD}-SkmrV^}u6iKGZKPQ8Q-m1+!_*m0 zYR@7I;WwxO8pB!ht6PQy2`#Ds-yFBTQZbQPKt1PSyoF!Q{Qk#DF{o)#xDR{+|DnNS zS#WQ=l$w-uCKN!kEP&zJbgB1wBsk6!hX#*n!Ko3V=-BfDk^g>wE`B_T00000NkvXX Hu0mjf*|Bt~ delta 893 zcmV-@1A_dW0+a`kB!2{FK}|sb0I$e51&Zka000?uMObuGZ)S9NVRB^vL1b@YWgtmy zVP|DhWnpA_ami&o0009fNklx$e+D>UXJXjccz|I= z<1vQiFtIFE28J?qpjx2%(n|~s00G1VlVD^7Vj%q=WY}M@fqxbZYO;P7>Ky5;j10^m zHOxQ-`a%p0KmH*s0SF)_1|+})G695v1~9NPXE6ANGPrrGS(%G4*n;HEL>L&{r5G5# z{Xysf2p|*#z?wm>_`#seq^=ymAb5{~(MFjyN|!l>4JenV0W|wRiVg;V0Ac}?e}P(m zG6*sJW)Nol$$udDpNS!v#ZsN0f#D$ogP0O1P}|ue_#Mf3F|ZP$Z{|;|KeleX6IoPm1Jj9{RNZ;h7`ji2DKDpeg$ozr5|3t z`@;N|@$=vJUp}$jdHVO?zyI|B0mSn4JHu9{f9!#r{(r{oOzcmA8omPYYoOkbK)-x{TWc; z>OY3hyZet<4 z*!Aug!+Dqj4qyzt{Kar>-y4R+!><`u0ojT`VNM1}C@}y85aa*CatJH*enD zym|ApXU~3}Za#bV?59tkjHC~W0aY-T1o;IsI6S+N2INF}x;TbNNU|PmWIU|E!)zeA z>Hq&+&3P;iOkxg9Iu1e#4wIrcI4~&)yFU?|u~dB4`RvFPdUE0!^?G4 xL8GOwN&fiJ2b<1GoO}DD>}i$5SqH`+%#*W}^cCzR1%b9Oc)I$ztaD0e0sy6gMv?#k literal 0 HcmV?d00001 diff --git a/textures/base/pack/server_flags_mt.png b/textures/base/pack/server_flags_mt.png new file mode 100644 index 0000000000000000000000000000000000000000..07003ae1372c8ada8ec800d9b99985cd0b976c27 GIT binary patch literal 432 zcmV;h0Z;ykP) zWwRP-yBlo86f-XnWUC%%p&D_`7izr~ah}dqVpPPS0O-?3IXpRXp3XosHEx>8(ZxqN zJwHE0ME2xQ<+g3*w{1d3MJrjNdH?_b2y{|TQveAT{uB-d0&PVzpa1{>rb$FWRCwAo z$^~)+K@3Ath2_R!3^Q}GaQ}m?hg9VM%D^#s0vuYqhiS}n0`{`DcIsY7*bqW*akRgH zHkpB(A%quJ^6{Vm9^~4gp*ZIhY)YnAD))45rEvEY<73-}K%SnRD=>}mqU}f#@7?b; zZpho`DU(N0000SgEi8 literal 0 HcmV?d00001 diff --git a/textures/base/pack/server_flags_pvp.png b/textures/base/pack/server_flags_pvp.png index 977dfdc0c35e4c1441d685dae1f6d4dc238f6887..600ec5534b6b34705b5aeb2a33fbc8465e558989 100644 GIT binary patch delta 235 zcmVd57BQhhlphttJ lLV>`WmB*P5aXkJ9`~wjJ1LxcSQ#t?u002ovPDHLkV1g!lWOe`m delta 1027 zcmV+e1pNDk0+R6BQf(|Nj600I9IOvbDUbtgyPj$E>ry&(+{QLrbTvxVgT@xx2udoS)Oy+PAvG zpr)^w8G(|^_2fPsT-ZEniT&8n@k z#>>%lc72zdqQS<@&(YP&%g#bXLWhWn5E2i=#K)+suDid*s;;xa!o>gp0RR90O-)Ua zl9T`c{{R30zQ4h{yuPWdudJ@Ju(7nfyuJVc0BC4u00026v9YPEtt%@o+1c5yuCKzu z#8pmLv9h+StbedkNK(VW#H6I7w6wHLOiFQWa;K)Dy}h@Ql9HL3nYy~Qt*xkHTViW# zZ1(p0QW!^_mY$xSod5s;q@<%+8Ao6)VymmMhK7ZmkfcEpK0+El$jHd4sH&%?snOBR zN+d-^6F;AytA&MwuCA?}lbv51L{=6)PZmWd8YYvIlz)|#mOC*#PZvg17CvAcMw*S9 ztE;C_P*HSNbRZx>Y({HzP;q;Bd{k6bm6MgQu&=$nx1F7zfq{pip`xFkp@D&f&CSL< zD@D7zwY0Rel#-NiaB8Wks@dJ*m6ev^A%#md#w*4n76uwooUTO35j&DsvBF^~WN0GV`BPE!B{EX4yT zea6^)r33*21E9*L?~?@rj_;Z$)Aff5f%w`fAAijHcWwUL9vI91`BX*y{oE1(5Xt`i z^VJFj0RjOGyZrk6{KE(WBKG+t0#ms<$jvjlS^@zlw(PK!?6WTc0l5C(4#&s_0VxcV zuj8wR;=rN}BDd@L`>z)i79Fel_VKVc%>oS5LkCfwl@|d40RaRFtcG3(aLOf00002! zNqp#&XjwYkXErgCfx4NRuLnQuvwWX3#Z>e1rnSCR!N*nCW1#%unO^+!x>Mxqd7 zmXl01FtiURbNS@W9%!Dsa49m7BVin!^L&o9NG=6%bpUTdOMNHNBJ6Stydo_F0MKzg z2}zQB>j8hQC3%`iULeGmy#h3RY}7YlW&FY_J*Wl<-Yc}$rLv8S=kg9jV4XGq9-2TL xAe#nGj{!Jy@R`o0B;^h-7Wlvb*uMq<;2%1&L7B#-2%-Q0002ovPDHLkV1l|N34#Cs diff --git a/textures/base/pack/server_ping_1.png b/textures/base/pack/server_ping_1.png index ba5bba1e3da6f6ae3340b499b291ee4f2108b553..3e06ad808bd24cc01d1566a173de49835d72b15e 100644 GIT binary patch delta 88 zcmey(ST;c=$kx-vF{I*FvVwe1)0Qn;{ww%wa!XEr45AqgcvYku)-lfYU(`FJW{%mU ooCE4{_kc317z=t+qz@QyF=Q}weP19J=g0sAp00i_>zopr0A`UQsQ>@~ delta 222 zcmXT>%{W1&o-N7S-Gw0<1hp>kbTBY5a29w(7Bet#3xhBt!>leT;-f9Qxr{F|>KzTkET zUxdfji3t({nu^tb=`k3De` pZ^rxQKll$p1z$*clpoY!U~o7vUGt*T4rc}+@O1TaS?83{1OV`qBw+vm delta 215 zcmb>W!Z<;to-N7S-G#vd1hX<+`WP4(I14-?iy0WWg+Z8+Vb&Z8pdfpRr>`sfLnbBx zL&luSTnnI3qo<2wh{fsTEgLo@EMPG(4B%*6z@C7;@_wLosaeZ3ukNjiO>14|KI$^#=u6$pIt`(A{4H=&CzSPdE$VA%O=L2 zjK-Ej@w=W#C^IuNH@7ae2(#-3l2=&YCkR>mxW2H)SH$jd!*e%==%a?NtuKr=0A0i2 M>FVdQ&MBb@0Ee|xLI3~& diff --git a/textures/base/pack/server_ping_3.png b/textures/base/pack/server_ping_3.png index c2cab017e10b3b6babfafe953cf663b7066cfa46..b3ff45e35fe4086d00f906ee3ded44f67521493b 100644 GIT binary patch delta 92 zcmey$ST#W<%+b@uF{I*FvVwe1)0Qn;{ww%wa!XEr45AtL%s2VhY;clogBsT#_QXlN r4Velz8D_8n8Ja*w3G0&G2_g&(^Ix=U&%cu7$N&VMu6{1-oD!M<4>TlZ delta 216 zcmb>W$~Zx#o-N7S-Gw0<1hp>kbTBY5a29w(7Bet#3xhBt!>l6iaWZGk!jvR->?a@WtM#C zKO}nWl^shJKWFF6i$VNSuiKbIu7+OC_Tw$!50adc`O!#s-*tZJDRpHGwXZ+&o$E+! z_G)?lQS_hcJ1LjWXyzy1b;Hw|Bf?Kde?L^foSFgDGxJ-SZ1sFF4BfSS#nj5 ls3#~V+O_pA*_|N5z;Nnw%f!1);(Hl@z|+;wWt~$(696<&9_Ii6 delta 184 zcmXTA$~Zx#o-N7S-GzaH;Xi{S_on%0fGo}ekH}&M25w;xW@MN(M*=9wUgGKN%Kngv zNx*=4c8+Z*P$U{?U)q{|)T8cbd)ru>aqD z4e1HlEcz-9*ItEWyKbLh*2~7YMFhG_7 diff --git a/textures/base/pack/trash.png b/textures/base/pack/trash.png new file mode 100644 index 0000000000000000000000000000000000000000..263b5674985a50a7f0913e0f84a4dfec8fc01757 GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e{s5m4*Z=?jw=gjLXJGu_+6rXP zvOK#KD8*P3R-UA98tQXcD;98epuJQYP$RGC1#cB#N ze>)9Nd4Es|=hkgn#3(S;wZq5ZRH>k%nL?4t4iiQ#-t*EYl$2LowqPjwtj_PEc43o{ z{fhld8veMS5|v6UXXaqF=xGq$Anl-WfUB9A@5N2l*bjOamNfnFm;V3uv9P+`*GH4h b?f%9~{Vw#F7P9d*&`AuQu6{1-oD!M<$tPAA literal 0 HcmV?d00001