--[[ ITB (insidethebox) minetest game - Copyright (C) 2017-2018 sofar & nore This library 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 library 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ]]-- --[[ game menu options for use with sfinv --]] local S = minetest.get_translator("menu") local FE = minetest.formspec_escape local function toggle_music(player) local pmeta = player:get_meta() local m = pmeta:get_string("music") if not m or m == "1" then music.stop(player) m = "0" minetest.chat_send_player(player:get_player_name(), S("Music is now disabled.")) else m = "1" minetest.chat_send_player(player:get_player_name(), S("Music is now enabled. Music playback will start later.")) end pmeta:set_string("music", m) end sfinv.register_page("menu:lobby", { title = S("Game"), is_in_nav = function(self, player, context) local name = player:get_player_name() return not boxes.players_editing_boxes[name] and not boxes.players_in_boxes[name] end, get = function(self, player, context) return sfinv.make_formspec(player, context, "button[0.5,0.5;4,0.6;music;"..FE(S("Toggle music")).."]" .. sfinv.get_hotbar_bg(0,4.7) .. sfinv.style.gui_bg .. sfinv.style.gui_bg_img .. sfinv.style.gui_slots .. creative.formspec_add, true) end, on_player_receive_fields = function(self, player, context, fields) if fields.music then toggle_music(player) end return end, }) local function callback_erase(player, fields, context) local name = player:get_player_name() if fields.btn_cancel or fields.quit then return true end if not fields.btn_erase or context ~= tonumber(fields.confirm) or not boxes.players_editing_boxes[name] then return true end -- wipe the box local box = boxes.players_editing_boxes[name] minetest.log("action", name .. " erases all content of box " .. box.box_id) local minp = vector.add(box.minp, 1) local maxp = vector.add(box.maxp, -1) -- wipe nodes with meta separately for _, p in ipairs(minetest.find_nodes_with_meta(minp, maxp)) do minetest.remove_node(p) end local cid_air = minetest.get_content_id("air") local vm = minetest.get_voxel_manip(minp, maxp) local emin, emax = vm:get_emerged_area() local va = VoxelArea:new{MinEdge=emin,MaxEdge=emax} local vmdata = vm:get_data() local param2 = vm:get_param2_data() for z = minp.z, maxp.z do for y = minp.y, maxp.y do local index = va:index(minp.x, y, z) for x = minp.x, maxp.x do vmdata[index] = cid_air param2[index] = 0 index = index + 1 end end end vm:set_data(vmdata) vm:set_param2_data(param2) vm:update_liquids() vm:write_to_map() vm:update_map() minetest.after(0.1, minetest.fix_light, minp, maxp) -- reset pedestal number, build time box.start_edit_time = minetest.get_gametime() box.num_items = 0 local bmeta = db.box_get_meta(box.box_id) bmeta.meta.num_items = 0 bmeta.meta.build_time = 0 db.box_set_meta(box.box_id, bmeta) return true end local function callback_landscape(player, fields, context) local name = player:get_player_name() if fields.btn_cancel or fields.quit then return true end if not fields.btn_landscape or context ~= tonumber(fields.confirm) or not boxes.players_editing_boxes[name] then return true end -- landscape the box local box = boxes.players_editing_boxes[name] minetest.log("action", name .. " landscapes box " .. box.box_id) local minp = vector.add(box.minp, 1) local maxp = vector.add(box.maxp, -1) local vm = minetest.get_voxel_manip(minp, maxp) local emin, emax = vm:get_emerged_area() local va = VoxelArea:new{MinEdge=emin,MaxEdge=emax} local vmdata = vm:get_data() local param2 = vm:get_param2_data() local cursor = 8 local stack for y = minp.y, maxp.y do local inv = player:get_inventory() while not stack or stack:is_empty() and cursor > 1 do stack = inv:get_stack("landscape", cursor) cursor = cursor - 1 end if not stack:is_empty() then local item = stack:take_item() local iname = item:get_name() if iname ~= "torches:torch" and minetest.registered_nodes[iname] then local cid = minetest.get_content_id(iname) for z = minp.z, maxp.z do local index = va:index(minp.x, y, z) for x = minp.x, maxp.x do vmdata[index] = cid param2[index] = 0 index = index + 1 end end end end end vm:set_data(vmdata) vm:set_param2_data(param2) vm:update_liquids() vm:write_to_map() vm:update_map() minetest.after(0.1, minetest.fix_light, minp, maxp) -- reset pedestal number, build time box.start_edit_time = minetest.get_gametime() box.num_items = 0 local bmeta = db.box_get_meta(box.box_id) bmeta.meta.num_items = 0 bmeta.meta.build_time = 0 db.box_set_meta(box.box_id, bmeta) return true end sfinv.register_page("menu:edit", { title = S("Game"), is_in_nav = function(self, player, context) local name = player:get_player_name() return boxes.players_editing_boxes[name] end, get = function(self, player, context) local name = player:get_player_name() local box = boxes.players_editing_boxes[name] local name_edit = "" if box and box.box_name ~= nil then name_edit = "field[0.8,2.6;4,0.6;box_name;"..FE(S("Box name"))..";" .. minetest.formspec_escape(box.box_name) .. "]" end local skyboxnr = 0 if box and box.skybox then skyboxnr = box.skybox end local skybox = "label[0.5,2.9;"..FE(S("Sky box:")).."]" .. "dropdown[0.5,3.3;4.0;skybox;" .. "0 - " .. FE(S("off")).."," .. "1 - " .. FE(S("Dark and Stormy")).."," .. "2 - " .. FE(S("Cloudy with light rays")).."," .. "3 - " .. FE(S("Full Moon")).."," .. "4 - " .. FE(S("Sunset")).."," .. "5 - " .. FE(S("Thick clouds over water")).."," .. "6 - " .. FE(S("Tropical sunny day")) .. ";" .. tostring(skyboxnr + 1) .."]" return sfinv.make_formspec(player, context, "button[0.5,0.5;4,0.6;save;"..FE(S("Save this box")).."]" .. "button[0.5,1.3;4,0.6;stopedit;"..FE(S("Stop editing this box")).."]" .. name_edit .. skybox .. "button[0.5,4.2;4,0.6;erase;"..FE(S("Wipe everything in this box")).."]" .. "button[0.5,5.0;4,0.6;landscape;"..FE(S("Landscape this box")).."]" .. "button[0.5,5.8;4,0.6;music;"..FE(S("Toggle music")).."]" .. sfinv.style.gui_bg .. sfinv.style.gui_bg_img .. sfinv.style.gui_slots, false) end, on_player_receive_fields = function(self, player, context, fields) if fields.stopedit then minetest.close_formspec(player:get_player_name(), "") boxes.save_edit(player) boxes.stop_edit(player) music.stop(player) players.return_to_lobby(player) return end -- don't elseif here - if text fields change we want to save them anyway. if fields.save then minetest.close_formspec(player:get_player_name(), "") boxes.save_edit(player) end if fields.skybox then local number = tonumber(fields.skybox:sub(1,1)) skybox.set(player, number) boxes.players_editing_boxes[player:get_player_name()].skybox = number end if fields.box_name then boxes.players_editing_boxes[player:get_player_name()].box_name = fields.box_name sfinv.set_player_inventory_formspec(player) end if fields.erase then local name = player:get_player_name() local token = math.random(10000, 99999) fsc.show(name, "size[10,7]" .. -- TODO: Change to multi-line label "textlist[0.5,0.5;8.7,2.0;restettext;" .. -- TODO: Make translatable "Erasing the content is irreversible\\, and can not," .. "be undone. Are you sure you want to continue?,," .. "If you are sure\\, then type \"" .. token .. "\" in this " .. "text box\\,and press \"Erase Everything\".;0;0]" .. "field[4.0,3.5;3.0,1.5;confirm;;]" .. "button[0.6,5.5;4.4,1.5;btn_cancel;"..FE(S("Cancel")).."]" .. "button[5.0,5.5;4.4,1.5;btn_erase;"..FE(S("Erase everything")).."]", token, callback_erase ) end if fields.landscape then local name = player:get_player_name() local token = math.random(10000, 99999) local inv = minetest.get_inventory({type="player", name = name}) inv:set_size("landscape", 10) fsc.show(name, "size[10,10]" .. "list[current_player:landscape;landscape;0.2,0;1,8;]" .. "list[current_player;main;1.6,0;8,1;]" .. "listring[]" .. "list[current_player;main;1.6,1.1;8,3;8]" .. -- TODO: Make translatable, use multi-line label "label[1.6,5;Drop nodes to the left from your inventory to create base layers for]" .. "label[1.6,5.4;your box with these nodes. The stack size determines the thickness]" .. "label[1.6,5.8;of the layers. Empty slots are omitted. Put torches in to leave]" .. "label[1.6,6.2;multiple layers empty. The blocks in those layers will not be removed.]" .. "label[1.6,7.6;Put the code \\\"" .. token .. "\\\" in the box here:]" .. "field[6.4,7.4;3.0,1.5;confirm;;]" .. "button[1.4,8.8;4,1.5;btn_cancel;"..FE(S("Cancel")).."]" .. "button[5.4,8.8;4,1.5;btn_landscape;"..FE(S("Landscape this box")).."]", token, callback_landscape ) end if fields.music then toggle_music(player) end end, }) sfinv.register_page("menu:play", { title = "Game", is_in_nav = function(self, player, context) local name = player:get_player_name() return boxes.players_in_boxes[name] end, get = function(self, player, context) local name = player:get_player_name() local box = boxes.players_in_boxes[name] local bmeta = db.box_get_meta(box.box_id) local label = "label[0.5,0.5;"..FE(S("You are in box @1: \"@2\" by @3", box.box_id, bmeta.meta.box_name, bmeta.meta.builder)) .. "]" local leave_btn = "button[0.5,2.1;4,0.6;leave;"..FE(S("Leave this box")).."]" if conf.tutorial.required then local pmeta = player:get_meta() if pmeta:get_string("tutorial_completed") ~= "1" then leave_btn = "" end end return sfinv.make_formspec(player, context, label .. leave_btn .. "button[0.5,1.3;4,0.6;music;"..FE(S("Toggle music")).."]" .. sfinv.get_hotbar_bg(0,4.7) .. sfinv.style.gui_bg .. sfinv.style.gui_bg_img .. sfinv.style.gui_slots .. creative.formspec_add, true) end, on_player_receive_fields = function(self, player, context, fields) if fields.leave then music.stop(player) minetest.close_formspec(player:get_player_name(), "") boxes.close_box(player) players.return_to_lobby(player) end if fields.music then toggle_music(player) end end, })