------------------------------------------------------------- --- 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 local found_type = ""; for k,w in ipairs( replacements_group[ group ].all ) do -- we have found the full block of that group type if( name == w ) then found_type = w; -- no primary node found; there may still be subordinate types else for nr,t in ipairs( replacements_group[ group ].data[ w ] ) do if( name==t and not( types_found_list[ w ])) then found_type = w; end end end end if( found_type ~= "" and not( types_found_list[ found_type ])) then extra_buttons.offset = extra_buttons.offset + 1; extra_buttons.text = extra_buttons.text.."button[9.9,".. tostring( (extra_buttons.offset*0.9)+2.8 )..";3.0,0.5;".. tostring( button_name )..";".. minetest.formspec_escape( found_type ).."]"; -- remember that we found and offered this type already; avoid duplicates types_found_list[ found_type ] = 1; end return extra_buttons; end 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 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 formspec = "tableoptions[" .. "color=#ff8000;" .. "background=#0368;" .. "border=true;" .. --"highlight=#00008040;" .. "highlight=#aaaaaaaa;" .. "highlight_text=#7fffff]" .. "tablecolumns[" .. "color;" .. "text,width=1,align=right;" .. "color;" .. "text,width=5;" .. "color;" .. "text,width=1;" .. "color;" .. "text,width=5]" .. -- "tabheader[".. -- "1,1;columns;amount,original material,,target material;1;true;true]".. "table[".. "0.5,2.7;9.4,6.8;build_chest_replacements;"; local j=1; local may_proceed = true; local replace_row_material = nil; local replace_row_with = ""; -- make sure the statistic has been created if( not( build_chest.building[ building_name ].statistic )) then if( not( build_chest.read_building( building_name ))) then return "label[2,2;Error: Unable to read building file.]"; end end -- used for setting wood type or plant(farming) type etc. local extra_buttons = { text = "", offset = 0}; -- there may be wood types that only occour as stairs and/or slabs etc., without full blocks local types_found_list_wood = {}; local types_found_list_farming = {}; local types_found_list_roof = {}; local not_the_first_entry = false; for i,v in ipairs( build_chest.building[ building_name ].statistic ) do local name = build_chest.building[ building_name ].nodenames[ v[1]]; -- nodes that are to be ignored do not need to be replaced if( name ~= 'air' and name ~= 'ignore' and name ~= 'mg:ignore' and v[2] and v[2]>0) then local anz = v[2]; -- find out if this node name gets replaced local repl = name; for j,r in ipairs( replacements ) do if( r and r[1]==name ) then repl = r[2]; end end -- avoid empty lines at the end if( not_the_first_entry ) then formspec = formspec..','; end formspec = formspec..'#fff,'..tostring( anz )..','; if( name == repl and repl and minetest.registered_nodes[ repl ]) then formspec = formspec.."#0ff,,#fff,,"; else if( name and minetest.registered_nodes[ name ] ) then formspec = formspec.."#0f0,"; -- green else formspec = formspec.."#ff0,"; -- yellow end formspec = formspec..name..',#fff,'..minetest.formspec_escape('-->')..','; end if( repl and (minetest.registered_nodes[ repl ] or repl=='air') ) then formspec = formspec.."#0f0,"..repl; -- green else formspec = formspec.."#ff0,?"; -- yellow may_proceed = false; -- we need a replacement for this material end if( j == replace_row ) then replace_row_material = name; if( repl ~= name ) then replace_row_with = repl; end end 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; not_the_first_entry = true; end end formspec = formspec.."]"; 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 if( extra_buttons.text and extra_buttons.text ~= "" ) then formspec = formspec..extra_buttons.text.. "label[9.9,2.8;Replace by type:]"; end if( replace_row_material ) then formspec = formspec.. "label[0.5,2.1;Replace ".. minetest.formspec_escape( replace_row_material ).."]".. "label[6.5,2.1;with:]".. "field[7.5,2.4;4,0.5;replace_row_with;;".. minetest.formspec_escape( replace_row_with ).."]".. "field[-10,-10;0.1,0.1;replace_row_material;;".. minetest.formspec_escape( replace_row_material ).."]".. "button[11.1,2.1;1,0.5;store_replacement;Store]"; end return formspec; end -- set replacements for all unknown nodes to air so that the building can be spawned build_chest.replacements_replace_rest_with_air = function( pos, meta ) local building_name = meta:get_string( 'building_name' ); if( not( building_name ) or not( build_chest.building[ building_name ])) then return; end local replacements_orig = minetest.deserialize( meta:get_string( 'replacements' )); for i,v in ipairs( build_chest.building[ building_name ].statistic ) do local name = build_chest.building[ building_name ].nodenames[ v[1]]; -- nodes that are to be ignored do not need to be replaced if( name ~= 'air' and name ~= 'ignore' and name ~= 'mg:ignore' and v[2] and v[2]>0) then -- find out if this node name gets replaced local repl = name; for j,r in ipairs( replacements_orig ) do if( r and r[1]==name ) then repl = r[2]; -- set replacements for inexisting nodes to air if( not( minetest.registered_nodes[ repl ] )) then r[2] = 'air'; end end end -- replace nodes that do not exist with air if( not( repl ) or not( minetest.registered_nodes[ repl ])) then table.insert( replacements_orig, { name, 'air' }); end end end -- store the new set of replacements meta:set_string( 'replacements', minetest.serialize( replacements_orig )); end 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 = 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; found = true; end end if( not( found )) then table.insert( replacements_orig, { old_material, new_material }); end -- store the new set of replacements build_chest.replacements_set_current( meta, village_id, replacements_orig ); end end build_chest.replacements_get_group_list_formspec = function( pos, group, button_name ) local formspec = ""; for i,v in ipairs( replacements_group[ group ].found ) do formspec = formspec.."item_image_button["..tostring(((i-1)%8)+1)..",".. tostring(3+math.floor((i-1)/8))..";1,1;".. tostring( v )..";"..tostring( button_name )..";"..tostring(i).."]"; end return formspec; end 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 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 build_chest.replacements_set_current( meta, village_id, replacements ); end