diff --git a/functions.lua b/functions.lua index 5ea4a6d..cc5223b 100644 --- a/functions.lua +++ b/functions.lua @@ -1697,10 +1697,113 @@ yl_speak_up.add_new_dialog = function(dialog, pname) return future_d_id end + +-- this is always called when switching to a new dialog; but only in edit_mode does +-- it show a formspec asking for change/back/discard +yl_speak_up.save_changes_and_switch_to_other_dialog = function(player, fields, target_dialog) + + if(not(target_dialog)) then + target_dialog = "" + end + + local pname = player:get_player_name() + -- if the player is not even talking to this particular npc + if(not(yl_speak_up.speak_to[pname])) then + return + end + + local edit_mode = (yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id) + local d_id = yl_speak_up.speak_to[pname].d_id + local n_id = yl_speak_up.speak_to[pname].n_id + + -- the player decided to go back and continue editing the current dialog + if(edit_mode and fields.back_to_dialog_changes) then + -- do NOT clear the list of changes; just show the old dialog again + minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, n_id, d_id)) + return + + -- save changes and continue on to the next dialog + elseif(edit_mode and fields.save_dialog_changes) then + -- actually save the dialog (the one the NPC currently has) + save_dialog(n_id, yl_speak_up.speak_to[pname].dialog) + -- clear list of changes + yl_speak_up.npc_was_changed[ n_id ] = {} + + -- discard changes and continue on to the next dialog + elseif(edit_mode and fields.discard_dialog_changes) then + -- actually restore the old state and discard the changes by loading the dialog anew + yl_speak_up.speak_to[pname].dialog = load_dialog(n_id) + -- clear list of changes + yl_speak_up.npc_was_changed[ n_id ] = {} + end + + -- are there any changes which might be saved or discarded? + if(edit_mode + and yl_speak_up.npc_was_changed[ n_id ] + and #yl_speak_up.npc_was_changed[ n_id ] > 0) then + + local target_name = "quit" + if(target_dialog and target_dialog ~= "") then + target_name = "go on to dialog "..minetest.formspec_escape(target_dialog) + end + + local d_id = yl_speak_up.speak_to[pname].d_id + -- reverse the order of the changes in the log so that newest are topmost + local text = "" + for i,t in ipairs(yl_speak_up.npc_was_changed[ n_id ]) do + -- some entries may be more than one line long + local tmp = "" + local parts = string.split(t, "\n", false) + for i, part in ipairs(parts) do + tmp = tmp..minetest.formspec_escape(part).."," + end + text = tmp..text + end + -- build a formspec showing the changes to this dialog and ask for save + local formspec = + "formspec_version[3]".. + "size[14,6.2]".. + "bgcolor[#00000000;false]".. + "label[0.2,0.2;You are about to leave dialog "..minetest.formspec_escape(d_id).. + " and "..target_name..".]".. + "label[0.2,0.65;These changes have been applied to dialog ".. + minetest.formspec_escape(d_id)..":]".. + "textlist[0.2,1;13.5,4;list_of_changes;"..text.."]".. + "button[1.2,5.2;3,0.9;discard_dialog_changes;Discard changes]".. + "button[5.7,5.2;3,0.9;back_to_dialog_changes;Back]".. + "button[10.2,5.2;3,0.9;save_dialog_changes;Save changes]".. + "tooltip[save_dialog_changes;Save all changes to this dialog and "..target_name..".]".. + "tooltip[discard_dialog_changes;Undo all changes and "..target_name..".]".. + "tooltip[back_to_dialog_changes;Go back to dialog ".. + minetest.formspec_escape(d_id).." and continue editing it.]".. + + -- hidden field telling about the target dialog + "field[20,20;0.1,0.1;goto_target_dialog;target_dialog;"..minetest.formspec_escape(target_dialog).."]" + -- actaully show the formspec to the player + minetest.show_formspec(pname, "yl_speak_up:confirm_save", formspec) + return + end + -- if there is nothing that needs to be saved or discarded: allow quit/exit + if fields.quit or fields.button_exit then + yl_speak_up.edit_mode[pname] = nil + -- Formspec was quit + yl_speak_up.speak_to[pname] = nil + return + end + -- end edit mode and start a new chat - but this time in normal mode + if not(target_dialog) or target_dialog == "" then + yl_speak_up.edit_mode[pname] = nil + target_dialog = nil + end + -- move on to the target dialog + yl_speak_up.speak_to[pname].d_id = target_dialog + minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, n_id, target_dialog)) +end + + -- helper function for formspec "yl_speak_up:talk" when a parameter was changed in edit mode; -- this is called when the player is in edit_mode (editing the NPC); -- the function checks if the player has changed any parameters --- TODO: implement the change detection and ask the user what to do (save? discard?) -- Parameters: -- pname player name -- fields the fields returned from the formspec @@ -1820,15 +1923,19 @@ yl_speak_up.edit_mode_apply_changes = function(pname, fields) fields["d_id"] = d_id fields["show_new_dialog"] = nil end - - -- TODO just for debugging - for k,v in pairs(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ]) do - minetest.chat_send_player(pname, v ) - end end -- end of yl_speak_up.edit_mode_apply_changes +minetest.register_on_player_receive_fields( + function(player, formname, fields) + if formname ~= "yl_speak_up:confirm_save" then + return + end + yl_speak_up.save_changes_and_switch_to_other_dialog(player, fields, fields.goto_target_dialog) + end +) + minetest.register_on_player_receive_fields( function(player, formname, fields) @@ -1865,16 +1972,14 @@ minetest.register_on_player_receive_fields( return -- end edit mode (does not require the priv; will only switch back to normal behaviour) elseif fields.button_end_edit_mode then - yl_speak_up.edit_mode[pname] = nil - -- start a new chat - but this time in normal mode - yl_speak_up.speak_to[pname].d_id = nil - minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, yl_speak_up.speak_to[pname].n_id, nil)) + -- if there are any changes done: ask first and don't end edit mode yet + yl_speak_up.save_changes_and_switch_to_other_dialog(player, fields, nil) return end if fields.quit or fields.button_exit then - -- Formspec was quit - yl_speak_up.speak_to[pname] = nil + -- if there are any changes done: ask first and don't quit yet + yl_speak_up.save_changes_and_switch_to_other_dialog(player, fields, nil) return end @@ -1948,8 +2053,8 @@ minetest.register_on_player_receive_fields( end end end - yl_speak_up.speak_to[pname].d_id = show_dialog - minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, yl_speak_up.speak_to[pname].n_id, show_dialog)) + -- if there are any changes done: ask first and don't switch to the new dialog yet + yl_speak_up.save_changes_and_switch_to_other_dialog(player, fields, show_dialog) return end @@ -2079,9 +2184,9 @@ minetest.register_on_player_receive_fields( end if v.r_type == "dialog" then if dialog.n_dialogs[v.r_value] ~= nil then - yl_speak_up.speak_to[pname].d_id = v.r_value - local n_id = yl_speak_up.speak_to[pname].n_id - minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, n_id, v.r_value)) + -- if there are any changes done: ask first and don't switch to the new dialog yet + yl_speak_up.save_changes_and_switch_to_other_dialog(player, fields, v.r_value) + return else say("This dialog does not exist") end