347 lines
11 KiB
Lua

--[[
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,
})