From 8d94018e5ef92eb86dc9bc1c2170c3118d359517 Mon Sep 17 00:00:00 2001 From: Sokomine Date: Thu, 23 Jun 2016 04:44:32 +0200 Subject: [PATCH] added better support for the plotmarkers from mg_villages mod --- build_chest.lua | 149 ++++++++++++++++++++-------- build_chest_handle_replacements.lua | 91 ++++++++++++----- 2 files changed, 175 insertions(+), 65 deletions(-) diff --git a/build_chest.lua b/build_chest.lua index 41e6fac..03f9c70 100644 --- a/build_chest.lua +++ b/build_chest.lua @@ -277,19 +277,87 @@ end +-- offer diffrent replacement groups +handle_schematics.get_formspec_group_replacement = function( pos, fields, formspec ) + + if( fields.set_wood and fields.set_wood ~= "" ) then + return formspec.. + "label[1,2.2;Select replacement for "..tostring( fields.set_wood )..".]".. + "label[1,2.5;Trees, saplings and other blocks will be replaced accordingly as well.]".. + -- invisible field that encodes the value given here + "field[-20,-20;0.1,0.1;set_wood;;"..minetest.formspec_escape( fields.set_wood ).."]".. + build_chest.replacements_get_group_list_formspec( pos, 'wood', 'wood_selection' ); + end + + if( fields.set_farming and fields.set_farming ~= "" ) then + return formspec.. + "label[1,2.5;Select the fruit the farm is going to grow:]".. + -- invisible field that encodes the value given here + "field[-20,-20;0.1,0.1;set_farming;;"..minetest.formspec_escape( fields.set_farming ).."]".. + build_chest.replacements_get_group_list_formspec( pos, 'farming', 'farming_selection' ); + end + + if( fields.set_roof and fields.set_roof ~= "" ) then + return formspec.. + "label[1,2.5;Select a roof type for the house:]".. + -- invisible field that encodes the value given here + "field[-20,-20;0.1,0.1;set_roof;;"..minetest.formspec_escape( fields.set_roof ).."]".. + build_chest.replacements_get_group_list_formspec( pos, 'roof', 'roof_selection' ); + end + return nil; +end + + + build_chest.update_formspec = function( pos, page, player, fields ) -- information about the village the build chest may belong to and about the owner local meta = minetest.get_meta( pos ); + local village_name = meta:get_string( 'village' ); local village_pos = minetest.deserialize( meta:get_string( 'village_pos' )); local owner_name = meta:get_string( 'owner' ); local building_name = meta:get_string('building_name' ); + -- are we dealing with a plotmarker inside a village? + local village_id = meta:get_string( 'village_id' ); + local plot_nr = meta:get_int( 'plot_nr' ); + if( village_id + and village_id~="" + and plot_nr + and plot_nr>0 + and mg_villages.all_villages + and mg_villages.all_villages[ village_id ] + and mg_villages.all_villages[ village_id ].to_add_data.bpos + and mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ]) then + + local v = mg_villages.all_villages[ village_id ]; + village_name = v.name; + -- the center of the village + village_pos = { x = v.vx, y = v.vh, z = v.vz }; + -- who has bought the plot? + owner_name = v.to_add_data.bpos[ plot_nr ].owner; + building_name = v.to_add_data.bpos[ plot_nr ].btype; + -- get the name of the blueprint the building was created from + if( mg_villages.BUILDINGS[ building_name ] ) then + building_name = tostring( mg_villages.BUILDINGS[ building_name ].scm ); + end + -- we also know where the building will start and end + + -- TODO: these may need to be set + --local start_pos = meta:get_string('start_pos'); + --local end_pos = minetest.deserialize( meta:get_string('end_pos')); + --local rotate = meta:get_string('rotate'); + --local mirror = meta:get_string('mirror'); + else + village_id = ""; + plot_nr = -1; + end + -- distance from village center local distance = math.floor( math.sqrt( (village_pos.x - pos.x ) * (village_pos.x - pos.x ) - + (village_pos.y - pos.y ) * (village_pos.x - pos.y ) - + (village_pos.z - pos.z ) * (village_pos.x - pos.z ) )); + + (village_pos.y - pos.y ) * (village_pos.y - pos.y ) + + (village_pos.z - pos.z ) * (village_pos.z - pos.z ) )); -- the statistic is needed for all the replacements later on as it also contains the list of nodenames if( building_name and building_name~=""and not( build_chest.building[ building_name ].size )) then @@ -317,10 +385,32 @@ build_chest.update_formspec = function( pos, page, player, fields ) .."label[7.3,0.4;from the village center]".. "label[0.3,0.8;Part of village:]" .."label[3.3,0.8;"..(village_name or "?").."]" .."label[7.3,0.8;located at "..(minetest.pos_to_string( village_pos ) or '?').."]".. - "label[0.3,1.2;Owned by:]" .."label[3.3,1.2;"..(owner_name or "?").."]".. + "label[0.3,1.2;Owned by:]" .."label[3.3,1.2;"..(owner_name or "- for sale -").."]".. "label[3.3,1.6;Click on a menu entry to select it:]".. build_chest.show_size_data( building_name ); + if( fields.show_materials and fields.show_materials ~= "" ) then + -- do not allow any changes; just show the materials and their replacements + return formspec..build_chest.replacements_get_list_formspec( pos, nil, 0, meta, village_id, building_name, -1 ); + end + + -- are we dealing with a plotmarker? if so, we are finished here + -- (we mostly wanted the header and the option to see the replacements) + if( village_id and village_id ~= "" ) then + -- TODO: actually implement the villages_* functions + return formspec.."button[3,3;3,0.5;villages_create_backup;Create backup of current stage]".. + "button[3,4;3,0.5;show_materials;Show materials used]".. + "button[3,5;3,0.5;villages_reset_building;Reset building]".. + "button[3,3;3,0.5;villages_remove_building;Remove building]"; + end + + -- the building has been placed; offer to restore a backup + local backup_file = meta:get_string('backup'); + if( backup_file and backup_file ~= "" ) then + return formspec.."button[3,3;3,0.5;restore_backup;Restore original landscape]".. + "button[3,4;3,0.5;show_materials;Show materials used]"; + end + local current_path = minetest.deserialize( meta:get_string( 'current_path' ) or 'return {}' ); if( #current_path > 0 ) then formspec = formspec.."button[9.9,0.4;2,0.5;back;Back]"; @@ -333,48 +423,23 @@ build_chest.update_formspec = function( pos, page, player, fields ) end - -- the building has been placed; offer to restore a backup - local backup_file = meta:get_string('backup'); - if( backup_file and backup_file ~= "" ) then - return formspec.."button[3,3;3,0.5;restore_backup;Restore original landscape]"; - end - -- offer diffrent replacement groups - if( fields.set_wood and fields.set_wood ~= "" ) then - return formspec.. - "label[1,2.2;Select replacement for "..tostring( fields.set_wood )..".]".. - "label[1,2.5;Trees, saplings and other blocks will be replaced accordingly as well.]".. - -- invisible field that encodes the value given here - "field[-20,-20;0.1,0.1;set_wood;;"..minetest.formspec_escape( fields.set_wood ).."]".. - build_chest.replacements_get_group_list_formspec( pos, 'wood', 'wood_selection' ); - end - - if( fields.set_farming and fields.set_farming ~= "" ) then - return formspec.. - "label[1,2.5;Select the fruit the farm is going to grow:]".. - -- invisible field that encodes the value given here - "field[-20,-20;0.1,0.1;set_farming;;"..minetest.formspec_escape( fields.set_farming ).."]".. - build_chest.replacements_get_group_list_formspec( pos, 'farming', 'farming_selection' ); - end - - if( fields.set_roof and fields.set_roof ~= "" ) then - return formspec.. - "label[1,2.5;Select a roof type for the house:]".. - -- invisible field that encodes the value given here - "field[-20,-20;0.1,0.1;set_roof;;"..minetest.formspec_escape( fields.set_roof ).."]".. - build_chest.replacements_get_group_list_formspec( pos, 'roof', 'roof_selection' ); + local formspec_group_replacement = handle_schematics.get_formspec_group_replacement( pos, fields, formspec ); + if( formspec_group_replacement ) then + return formspec_group_replacement; end if( fields.preview and building_name ) then return formspec..build_chest.preview_image_formspec( building_name, - minetest.deserialize( meta:get_string( 'replacements' )), fields.preview); + build_chest.replacements_get_current( meta, village_id ), fields.preview); end -- show list of all node names used local start_pos = meta:get_string('start_pos'); if( building_name and building_name ~= '' and start_pos and start_pos ~= '' and meta:get_string('replacements')) then - return formspec..build_chest.replacements_get_list_formspec( pos ); + -- allow changes to the replacement list + return formspec..build_chest.replacements_get_list_formspec( pos, nil, 1, meta, village_id, building_name, -1 ); end -- find out where we currently are in the menu tree @@ -412,7 +477,8 @@ build_chest.update_formspec = function( pos, page, player, fields ) replacements_group['discontinued_nodes'].replace( replacements ); meta:set_string( 'replacements', minetest.serialize( replacements )); - return formspec..build_chest.replacements_get_list_formspec( pos ); + -- allow changes to be made + return formspec..build_chest.replacements_get_list_formspec( pos, nil, 1, meta, village_id, building_name, -1 ); elseif( type(start_pos)=='string' ) then return formspec.."label[3,3;Error reading building data:]".. "label[3.5,3.5;"..start_pos.."]"; @@ -562,21 +628,21 @@ build_chest.on_receive_fields = function(pos, formname, fields, player) and fields.replace_row_with and fields.replace_row_with ~= "" and fields.replace_row_material and fields.replace_row_material ~= "") then - build_chest.replacements_apply( pos, meta, fields.replace_row_material, fields.replace_row_with ); + build_chest.replacements_apply( pos, meta, fields.replace_row_material, fields.replace_row_with, nil ); elseif( fields.replace_rest_with_air ) then build_chest.replacements_replace_rest_with_air( pos, meta ); elseif( fields.wood_selection ) then - build_chest.replacements_apply_for_group( pos, meta, 'wood', fields.wood_selection, fields.set_wood ); + build_chest.replacements_apply_for_group( pos, meta, 'wood', fields.wood_selection, fields.set_wood, nil ); fields.set_wood = nil; elseif( fields.farming_selection ) then - build_chest.replacements_apply_for_group( pos, meta, 'farming', fields.farming_selection, fields.set_farming ); + build_chest.replacements_apply_for_group( pos, meta, 'farming', fields.farming_selection, fields.set_farming, nil ); fields.set_farming = nil; elseif( fields.roof_selection ) then - build_chest.replacements_apply_for_group( pos, meta, 'roof', fields.roof_selection, fields.set_roof ); + build_chest.replacements_apply_for_group( pos, meta, 'roof', fields.roof_selection, fields.set_roof, nil ); fields.set_roof = nil; @@ -602,7 +668,7 @@ build_chest.on_receive_fields = function(pos, formname, fields, player) end -- TODO: use scaffolding here (exchange some replacements) - local replacement_list = minetest.deserialize( meta:get_string( 'replacements' )); + local replacement_list = build_chest.replacements_get_current( meta, village_id ); local rotate = meta:get_string('rotate'); local mirror = meta:get_string('mirror'); local axis = build_chest.building[ building_name ].axis; @@ -610,7 +676,7 @@ build_chest.on_receive_fields = function(pos, formname, fields, player) -- actually place the building --minetest.place_schematic( start_pos, building_name..'.mts', rotate, replacement_list, true ); mirror = nil; - fields.error_msg = handle_schematics.place_building_from_file( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker ); + fields.error_msg = handle_schematics.place_building_from_file( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, false ); if( fields.error_msg ) then fields.error_msg = 'Error: '..tostring( fields.error_msg ); end @@ -630,7 +696,6 @@ mirror = nil; end end - -- store a new end position elseif( fields.set_end_pos ) then local node = minetest.get_node( pos ); diff --git a/build_chest_handle_replacements.lua b/build_chest_handle_replacements.lua index f09e0a3..099a8da 100644 --- a/build_chest_handle_replacements.lua +++ b/build_chest_handle_replacements.lua @@ -2,6 +2,41 @@ --- contains the handling of replacements for the build chest ------------------------------------------------------------- +build_chest.replacements_get_current = function( meta, village_id ) + + -- villages have their own replacement list for the entire village + if( village_id~="" + and mg_villages.all_villages + and mg_villages.all_villages[ village_id ] + and mg_villages.all_villages[ village_id ].to_add_data + and mg_villages.all_villages[ village_id ].to_add_data.replacements) then + + return mg_villages.all_villages[ village_id ].to_add_data.replacements; + end + + -- but usually, we store the replacement list in the build chest itself + return minetest.deserialize( meta:get_string( 'replacements' )); +end + + +-- store the new set of replacements +build_chest.replacements_set_current = function( meta, village_id, replacements ) + + -- villages have their own replacement list for the entire village + if( village_id~="" + and mg_villages.all_villages + and mg_villages.all_villages[ village_id ] + and mg_villages.all_villages[ village_id ].to_add_data + and mg_villages.all_villages[ village_id ].to_add_data.replacements) then + + mg_villages.all_villages[ village_id ].to_add_data.replacements = replacements; + end + + -- but usually, we store the replacement list in the build chest itself + meta:set_string( 'replacements', minetest.serialize( replacements )); +end + + -- internal function build_chest.replacements_get_extra_buttons = function( group, name, types_found_list, button_name, extra_buttons ) -- find out if there are any nodes that may need a group replacement @@ -33,17 +68,18 @@ end -build_chest.replacements_get_list_formspec = function( pos, selected_row ) +build_chest.replacements_get_list_formspec = function( pos, selected_row, allow_changes, meta, village_id, building_name, replace_row ) if( not( pos )) then return ""; end - local meta = minetest.env:get_meta( pos ); - local replacements = minetest.deserialize( meta:get_string( 'replacements' )); - local building_name = meta:get_string( 'building_name' ); + local replacements = build_chest.replacements_get_current( meta, village_id ); + if( replace_row == -1 and meta and (not( building_name ) or building_name =="" )) then + building_name = meta:get_string( 'building_name' ); + replace_row = meta:get_int('replace_row'); + end if( not( building_name ) or not( build_chest.building[ building_name ])) then return ""; end - local replace_row = meta:get_int('replace_row'); local formspec = "tableoptions[" .. "color=#ff8000;" .. @@ -129,9 +165,11 @@ build_chest.replacements_get_list_formspec = function( pos, selected_row ) end end - extra_buttons = build_chest.replacements_get_extra_buttons( 'wood', name, types_found_list_wood, 'set_wood', extra_buttons ); - extra_buttons = build_chest.replacements_get_extra_buttons( 'farming', name, types_found_list_farming, 'set_farming', extra_buttons ); - extra_buttons = build_chest.replacements_get_extra_buttons( 'roof', name, types_found_list_farming, 'set_roof', extra_buttons ); + if( allow_changes==1 ) then + extra_buttons = build_chest.replacements_get_extra_buttons( 'wood', name, types_found_list_wood, 'set_wood', extra_buttons ); + extra_buttons = build_chest.replacements_get_extra_buttons( 'farming', name, types_found_list_farming, 'set_farming', extra_buttons ); + extra_buttons = build_chest.replacements_get_extra_buttons( 'roof', name, types_found_list_farming, 'set_roof', extra_buttons ); + end j=j+1; @@ -139,13 +177,20 @@ build_chest.replacements_get_list_formspec = function( pos, selected_row ) end end formspec = formspec.."]"; - -- add the proceed-button as soon as all unkown materials have been replaced - if( may_proceed ) then - formspec = formspec.."button[9.9,9.0;2.0,0.5;proceed_with_scaffolding;Proceed]"; - else - formspec = formspec.."button[9.9,9.0;3.2,0.5;replace_rest_with_air;Suggest air for unknown]"; + if( allow_changes==0) then + return formspec.."label[0.5,2.1;Materials and replacements used:]".. + -- the back button returns a diffrent (unimportant) value here so that we don't accidently go too far back + "button[9.9,0.4;2,0.5;back_from_show_materials;Back]"; + end + if( meta ) then + -- add the proceed-button as soon as all unkown materials have been replaced + if( may_proceed ) then + formspec = formspec.."button[9.9,9.0;2.0,0.5;proceed_with_scaffolding;Proceed]"; + else + formspec = formspec.."button[9.9,9.0;3.2,0.5;replace_rest_with_air;Suggest air for unknown]"; + end + formspec = formspec.."button[9.9,1.0;2.0,0.5;preview;Preview]"; end - formspec = formspec.."button[9.9,1.0;2.0,0.5;preview;Preview]"; if( extra_buttons.text and extra_buttons.text ~= "" ) then formspec = formspec..extra_buttons.text.. "label[9.9,2.8;Replace by type:]"; @@ -200,13 +245,13 @@ end -build_chest.replacements_apply = function( pos, meta, old_material, new_material ) +build_chest.replacements_apply = function( pos, meta, old_material, new_material, village_id ) -- a new value has been entered - we do not need to remember the row any longer meta:set_int('replace_row', 0 ); local found = false; -- only accept replacements which can actually be placed if( new_material=='air' or minetest.registered_nodes[ new_material ] ) then - local replacements_orig = minetest.deserialize( meta:get_string( 'replacements' )); + local replacements_orig = build_chest.replacements_get_current( meta, village_id ); for i,v in ipairs(replacements_orig) do if( v and v[1]==old_material ) then v[2] = new_material; @@ -217,7 +262,7 @@ build_chest.replacements_apply = function( pos, meta, old_material, new_material table.insert( replacements_orig, { old_material, new_material }); end -- store the new set of replacements - meta:set_string( 'replacements', minetest.serialize( replacements_orig )); + build_chest.replacements_set_current( meta, village_id, replacements_orig ); end end @@ -233,24 +278,24 @@ build_chest.replacements_get_group_list_formspec = function( pos, group, button_ end -build_chest.replacements_apply_for_group = function( pos, meta, group, selected, old_material ) +build_chest.replacements_apply_for_group = function( pos, meta, group, selected, old_material, village_id ) local nr = tonumber( selected ); if( not(nr) or nr <= 0 or nr > #replacements_group[ group ].found ) then return; end local new_material = replacements_group[ group ].found[ nr ]; - if( old_material and old_material == new_material ) then - return; - end +-- if( old_material and old_material == new_material ) then +-- return; +-- end - local replacements = minetest.deserialize( meta:get_string( 'replacements' )); + local replacements = build_chest.replacements_get_current( meta, village_id ); if( not( replacements )) then replacements = {}; end replacements_group[ group ].replace_material( replacements, old_material, new_material ); -- store the new set of replacements - meta:set_string( 'replacements', minetest.serialize( replacements )); + build_chest.replacements_set_current( meta, village_id, replacements ); end