From 4c6a98b5936b0a3cb2f1f70ae3efc4c776b906e4 Mon Sep 17 00:00:00 2001 From: Diego Martinez Date: Wed, 6 May 2015 20:36:34 -0300 Subject: [PATCH] books: Allow editing while placed and open. Removes the ability to edit the book by "using" it, but instead allows to edit the book by right-clicking it while open. Also changes the interface to open/close the books by punching instead of right-clicking. In addition, fixes wrong handling of metadata. --- homedecor/books.lua | 90 +++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/homedecor/books.lua b/homedecor/books.lua index 0a6cfc6..725e77a 100644 --- a/homedecor/books.lua +++ b/homedecor/books.lua @@ -11,6 +11,8 @@ local bookcolors = { local BOOK_FORMNAME = "homedecor:book_form" +local player_current_book = { } + for c in ipairs(bookcolors) do local color = bookcolors[c][1] local color_d = S(bookcolors[c][1]) @@ -19,9 +21,15 @@ for c in ipairs(bookcolors) do local function book_dig(pos, node, digger) if minetest.is_protected(pos, digger:get_player_name()) then return end local meta = minetest.get_meta(pos) + local data = minetest.serialize({ + title = meta:get_string("title") or "", + text = meta:get_string("text") or "", + owner = meta:get_string("owner") or "", + _recover = meta:get_string("_recover") or "", + }) local stack = ItemStack({ name = "homedecor:book_"..color, - metadata = meta:get_string("text"), + metadata = data, }) stack = digger:get_inventory():add_item("main", stack) if not stack:is_empty() then @@ -44,7 +52,7 @@ for c in ipairs(bookcolors) do groups = { snappy=3, oddly_breakable_by_hand=3, book=1 }, walkable = false, stack_max = 1, - on_rightclick = function(pos, node, clicker) + on_punch = function(pos, node, puncher, pointed_thing) local fdir = node.param2 minetest.swap_node(pos, { name = "homedecor:book_open_"..color, param2 = fdir }) end, @@ -67,8 +75,17 @@ for c in ipairs(bookcolors) do }) local text = itemstack:get_metadata() or "" local meta = minetest.get_meta(pos) - meta:set_string("text", text) local data = minetest.deserialize(text) or {} + if type(data) ~= "table" then + data = {} + -- Store raw metadata in case some data is lost by the + -- transition to the new meta format, so it is not lost + -- and can be recovered if needed. + meta:set_string("_recover", text) + end + meta:set_string("title", data.title or "") + meta:set_string("text", data.text or "") + meta:set_string("owner", data.owner or "") if data.title and data.title ~= "" then meta:set_string("infotext", data.title) end @@ -78,31 +95,6 @@ for c in ipairs(bookcolors) do return itemstack end, on_dig = book_dig, - on_use = function(itemstack, user, pointed_thing) - local player_name = user:get_player_name() - local data = minetest.deserialize(itemstack:get_metadata()) - local title, text, owner = "", "", player_name - if data then - title, text, owner = data.title, data.text, data.owner - end - local formspec - if owner == player_name then - formspec = "size[8,8]"..default.gui_bg..default.gui_bg_img.. - "field[0.5,1;7.5,0;title;Book title :;".. - minetest.formspec_escape(title).."]".. - "textarea[0.5,1.5;7.5,7;text;Book content :;".. - minetest.formspec_escape(text).."]".. - "button_exit[2.5,7.5;3,1;save;Save]" - else - formspec = "size[8,8]"..default.gui_bg.. - "button_exit[7,0.25;1,0.5;close;X]".. - default.gui_bg_img.. - "label[0.5,0.5;by "..owner.."]".. - "label[0.5,0;"..minetest.formspec_escape(title).."]".. - "textarea[0.5,1.5;7.5,7;;"..minetest.formspec_escape(text)..";]" - end - minetest.show_formspec(user:get_player_name(), BOOK_FORMNAME, formspec) - end, selection_box = { type = "fixed", fixed = {-0.2, -0.5, -0.25, 0.2, -0.35, 0.25} @@ -121,6 +113,31 @@ for c in ipairs(bookcolors) do walkable = false, on_dig = book_dig, on_rightclick = function(pos, node, clicker) + local meta = minetest.get_meta(pos) + local player_name = clicker:get_player_name() + local title = meta:get_string("title") or "" + local text = meta:get_string("text") or "" + local owner = meta:get_string("owner") or "" + local formspec + if owner == "" or owner == player_name then + formspec = "size[8,8]"..default.gui_bg..default.gui_bg_img.. + "field[0.5,1;7.5,0;title;Book title :;".. + minetest.formspec_escape(title).."]".. + "textarea[0.5,1.5;7.5,7;text;Book content :;".. + minetest.formspec_escape(text).."]".. + "button_exit[2.5,7.5;3,1;save;Save]" + else + formspec = "size[8,8]"..default.gui_bg.. + "button_exit[7,0.25;1,0.5;close;X]".. + default.gui_bg_img.. + "label[0.5,0.5;by "..owner.."]".. + "label[0.5,0;"..minetest.formspec_escape(title).."]".. + "textarea[0.5,1.5;7.5,7;;"..minetest.formspec_escape(text)..";]" + end + player_current_book[player_name] = pos + minetest.show_formspec(player_name, BOOK_FORMNAME, formspec) + end, + on_punch = function(pos, node, puncher, pointed_thing) local fdir = node.param2 minetest.swap_node(pos, { name = "homedecor:book_"..color, param2 = fdir }) minetest.sound_play("homedecor_book_close", { @@ -141,15 +158,16 @@ minetest.register_on_player_receive_fields(function(player, form_name, fields) if form_name ~= BOOK_FORMNAME or not fields.save then return end - local stack = player:get_wielded_item() - if minetest.get_item_group(stack:get_name(), "book") == 0 then - return + local player_name = player:get_player_name() + local pos = player_current_book[player_name] + if not pos then return end + local meta = minetest.get_meta(pos) + meta:set_string("title", fields.title or "") + meta:set_string("text", fields.text or "") + meta:set_string("owner", player_name) + if (fields.title or "") ~= "" then + meta:set_string("infotext", fields.title) end - local data = minetest.deserialize(stack:get_metadata()) or {} - data.title, data.text, data.owner = - fields.title, fields.text, player:get_player_name() - stack:set_metadata(minetest.serialize(data)) - player:set_wielded_item(stack) minetest.log("action", player:get_player_name().." has written in a book (title: \""..fields.title.."\"): \""..fields.text.. "\" at location: "..minetest.pos_to_string(player:getpos())) end)