From 62aa08826b20fd54c93bc3eaf32f4655b14bc133 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sat, 15 Aug 2015 00:23:55 -0500 Subject: [PATCH] mg_villages and cottages updates --- mods/cottages/init.lua | 17 ++ mods/cottages/nodes_straw.lua | 120 +++++---- .../analyze_mc_schematic_file.lua | 2 +- mods/handle_schematics/build_chest.lua | 20 +- .../build_chest_add_schems_by_directory.lua | 23 ++ mods/handle_schematics/init.lua | 10 +- .../replacements_farming.lua | 4 +- mods/handle_schematics/replacements_wood.lua | 4 +- mods/mg_villages/buildings.lua | 20 -- mods/mg_villages/config.lua | 7 + mods/mg_villages/mapgen.lua | 139 ++++++++--- mods/mg_villages/nodes.lua | 38 +++ mods/mg_villages/protection.lua | 236 ++++++++++++------ mods/mg_villages/replacements.lua | 68 +---- mods/mg_villages/schems/baking_house_1.mts | Bin 967 -> 1095 bytes mods/mg_villages/schems/baking_house_2.mts | Bin 967 -> 1179 bytes mods/mg_villages/schems/baking_house_3.mts | Bin 1064 -> 1206 bytes mods/mg_villages/schems/baking_house_4.mts | Bin 1173 -> 1323 bytes mods/mg_villages/schems/mill_1.mts | Bin 773 -> 811 bytes mods/mg_villages/village_types.lua | 2 - mods/mg_villages/villages.lua | 6 +- 21 files changed, 461 insertions(+), 255 deletions(-) diff --git a/mods/cottages/init.lua b/mods/cottages/init.lua index 809f63b..af0cb16 100755 --- a/mods/cottages/init.lua +++ b/mods/cottages/init.lua @@ -36,6 +36,23 @@ end -- (i.e. in combination with realtest) dofile(minetest.get_modpath("cottages").."/adaptions.lua"); +-- add to this table what you want the handmill to convert; +-- add a stack size if you want a higher yield +cottages.handmill_product = {}; +cottages.handmill_product[ cottages.craftitem_seed_wheat ] = 'farming:flour 1'; +--[[ some examples: +cottages.handmill_product[ 'default:cobble' ] = 'default:gravel'; +cottages.handmill_product[ 'default:gravel' ] = 'default:sand'; +cottages.handmill_product[ 'default:sand' ] = 'default:dirt 2'; +cottages.handmill_product[ 'flowers:rose' ] = 'dye:red 6'; +cottages.handmill_product[ 'default:cactus' ] = 'dye:green 6'; +cottages.handmill_product[ 'default:coal_lump'] = 'dye:black 6'; +--]] +-- process that many inputs per turn +cottages.handmill_max_per_turn = 20; +cottages.handmill_min_per_turn = 0; + + -- uncomment parts you do not want dofile(minetest.get_modpath("cottages").."/nodes_furniture.lua"); dofile(minetest.get_modpath("cottages").."/nodes_historic.lua"); diff --git a/mods/cottages/nodes_straw.lua b/mods/cottages/nodes_straw.lua index 67499b4..13812d5 100755 --- a/mods/cottages/nodes_straw.lua +++ b/mods/cottages/nodes_straw.lua @@ -343,69 +343,54 @@ minetest.register_node("cottages:threshing_floor", { }) +local cottages_handmill_formspec = "size[8,8]".. + "image[0,1;1,1;"..cottages.texture_wheat_seed.."]".. + "list[current_name;seeds;1,1;1,1;]".. + "list[current_name;flour;5,1;2,2;]".. + "label[0,0.5;"..S("Wheat seeds:").."]".. + "label[4,0.5;"..S("Flour:").."]".. + "label[0,-0.3;"..S("Mill").."]".. + "label[0,2.5;"..S("Punch this hand-driven mill").."]".. + "label[0,3.0;"..S("to convert wheat seeds into flour.").."]".. + "list[current_player;main;0,4;8,4;]"; + minetest.register_node("cottages:handmill", { - drawtype = "nodebox", - description = S("Mill, powered by punching"), - tiles = {"default_stone.png"}, + description = S("mill, powered by punching"), + drawtype = "mesh", + mesh = "cottages_handmill.obj", + tiles = {"cottages_stone.png"}, paramtype = "light", - paramtype2 = "facedir", + paramtype2 = "facedir", groups = {cracky=2}, - node_box = { - type = "fixed", - fixed = { - - -- taken from 3dfornitures tree redefinition - {-0.35,-0.50,-0.4, 0.35,-0.32,0.4}, - {-0.4, -0.50,-0.35, 0.4, -0.32,0.35}, - {-0.25,-0.50,-0.45, 0.25,-0.32,0.45}, - {-0.45,-0.50,-0.25, 0.45,-0.32,0.25}, - {-0.15,-0.50,-0.5, 0.15,-0.32,0.5}, - {-0.5, -0.50,-0.15, 0.5, -0.32,0.15}, - - -- upper mill wheel - {-0.35,-0.27,-0.4, 0.35,-0.05,0.4}, - {-0.4, -0.27,-0.35, 0.4, -0.05,0.35}, - {-0.25,-0.27,-0.45, 0.25,-0.05,0.45}, - {-0.45,-0.27,-0.25, 0.45,-0.05,0.25}, - {-0.15,-0.27,-0.5, 0.15,-0.05,0.5}, - {-0.5, -0.27,-0.15, 0.5, -0.05,0.15}, - - -- middle axis - {-0.05,-0.50,-0.05, 0.05, 0.15,0.05}, - -- handle - {-0.35,-0.05,-0.35,-0.25, 0.25,-0.25}, - } - }, + is_ground_content = false, selection_box = { type = "fixed", fixed = { {-0.50, -0.5,-0.50, 0.50, 0.25, 0.50}, } }, + collision_box = { + type = "fixed", + fixed = { + {-0.50, -0.5,-0.50, 0.50, 0.25, 0.50}, + } + }, on_construct = function(pos) - - local meta = minetest.env:get_meta(pos); + local meta = minetest.get_meta(pos); meta:set_string("infotext", S("Mill, powered by punching")); local inv = meta:get_inventory(); inv:set_size("seeds", 1); inv:set_size("flour", 4); + meta:set_string("formspec", cottages_handmill_formspec ); end, after_place_node = function(pos, placer) local meta = minetest.get_meta(pos); meta:set_string("owner", placer:get_player_name() or ""); meta:set_string("infotext", S("Mill, powered by punching (owned by %s)"):format(meta:get_string("owner") or "")); - meta:set_string("formspec", - "size[8,8]".. - "list[current_name;seeds;1,1;1,1;]".. - "list[current_name;flour;5,1;2,2;]".. - "label[0,0.5;"..S("Grind This:").."]".. - "label[4,0.5;"..S("Ground Object:").."]".. - "label[0,0.1;"..S("Mill").."]".. - "label[2.5,0.1;"..S("Owner: %s"):format(meta:get_string('owner') or "").."]".. - "label[0,2.5;"..S("Punch this hand-driven mill").."]".. - "label[0,3.0;"..S("to grind various items.").."]".. - "list[current_player;main;0,4;8,4;]"); + meta:set_string("formspec", + cottages_handmill_formspec.. + "label[2.5,-0.5;"..S("Owner: %s"):format(meta:get_string('owner') or "").."]" ); end, can_dig = function(pos,player) @@ -426,7 +411,7 @@ minetest.register_node("cottages:handmill", { allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) local meta = minetest.get_meta(pos) - if( player and player:get_player_name() ~= meta:get_string('owner' )) then + if( not( cottages_can_use( meta, player ))) then return 0 end return count; @@ -434,15 +419,21 @@ minetest.register_node("cottages:handmill", { allow_metadata_inventory_put = function(pos, listname, index, stack, player) local meta = minetest.get_meta(pos) - if( player and player:get_player_name() ~= meta:get_string('owner' )) then - return 0 + -- only accept input the threshing floor can use/process + if( listname=='flour' + or (listname=='seeds' and stack and not( cottages.handmill_product[ stack:get_name()] ))) then + return 0; + end + + if( not( cottages_can_use( meta, player ))) then + return 0 end return stack:get_count() end, allow_metadata_inventory_take = function(pos, listname, index, stack, player) local meta = minetest.get_meta(pos) - if( player and player:get_player_name() ~= meta:get_string('owner' )) then + if( not( cottages_can_use( meta, player ))) then return 0 end return stack:get_count() @@ -456,28 +447,49 @@ minetest.register_node("cottages:handmill", { end local name = puncher:get_player_name(); - local meta = minetest.env:get_meta(pos); + local meta = minetest.get_meta(pos); local inv = meta:get_inventory(); local input = inv:get_list('seeds'); local stack1 = inv:get_stack( 'seeds', 1); - if( ( stack1:is_empty()) or( not( stack1:is_empty()) and stack1:get_definition().ground == nil )) then + if( ( stack1:is_empty()) + or( not( stack1:is_empty()) + and not( cottages.handmill_product[ stack1:get_name() ] ))) then + if not( stack1:is_empty() ) then minetest.chat_send_player(name,"Nothing happens...") end + -- update the formspec + meta:set_string("formspec", + cottages_handmill_formspec.. + "label[2.5,-0.5;"..S("Owner: %s"):format(meta:get_string('owner') or "").."]" ); return; end - local anz = 1 + math.random( 0, 3 ); + -- turning the mill is a slow process; 1-21 flour are generated per turn + local anz = 1 + math.random( cottages.handmill_min_per_turn, cottages.handmill_max_per_turn ); + -- we already made sure there is only wheat inside local found = stack1:get_count(); - if( inv:room_for_item('flour',stack1:get_definition().ground.." "..tostring(anz))) then + -- do not process more wheat than present in the input slots + if( found < anz ) then + anz = found; + end - inv:add_item("flour", stack1:get_definition().ground.." "..tostring(anz) ); - inv:remove_item("seeds", stack1:get_name()); + local product_stack = ItemStack( cottages.handmill_product[ stack1:get_name() ]); + local anz_result = anz; + -- items that produce more + if( product_stack:get_count()> 1 ) then + anz_result = anz * product_stack:get_count(); + end - local anz_left = found - 1; + if( inv:room_for_item('flour', product_stack:get_name()..' '..tostring( anz_result ))) then + + inv:add_item( 'flour', product_stack:get_name()..' '..tostring( anz_result )); + inv:remove_item( 'seeds', stack1:get_name()..' '..tostring( anz )); + + local anz_left = found - anz; if( anz_left > 0 ) then minetest.chat_send_player( name, S('You have ground a %s (%s are left).'):format(stack1:get_definition().description,(anz_left))); else diff --git a/mods/handle_schematics/analyze_mc_schematic_file.lua b/mods/handle_schematics/analyze_mc_schematic_file.lua index 458510e..fb0d482 100755 --- a/mods/handle_schematics/analyze_mc_schematic_file.lua +++ b/mods/handle_schematics/analyze_mc_schematic_file.lua @@ -199,7 +199,7 @@ print('FILE SIZE: '..tostring( string.len( data_string ))); -- TODO end -- print a few warning messages in case something goes wrong - but do not exaggerate if( not( new_node[2] and max_msg>0)) then - print('[handle_schematics:schematic] MISSING param2: '..minetest.serialize( new_node )); +-- print('[handle_schematics:schematic] MISSING param2: '..minetest.serialize( new_node )); new_node[2]=0; max_msg=max_msg-1; end diff --git a/mods/handle_schematics/build_chest.lua b/mods/handle_schematics/build_chest.lua index 64fc47a..4cf3a24 100755 --- a/mods/handle_schematics/build_chest.lua +++ b/mods/handle_schematics/build_chest.lua @@ -762,7 +762,14 @@ mirror = nil; build_chest.stages_on_receive_fields(pos, formname, fields, player, meta); end - meta:set_string( 'formspec', build_chest.update_formspec( pos, 'main', player, fields )); + local formspec = build_chest.update_formspec( pos, 'main', player, fields ); + -- add the position information so that we can show the formspec directly and still find out + -- which build chest was responsible + formspec = formspec.."field[20,20;0.1,0.1;pos2str;Pos;"..minetest.pos_to_string( pos ).."]"; + -- save the formspec data to the chest + meta:set_string( 'formspec', formspec ); + -- show the formspec directly to the player to make it react more smoothly + minetest.show_formspec( pname, "handle_schematics:build", formspec ); end @@ -844,6 +851,7 @@ minetest.register_node("handle_schematics:build", { --TODO if( stage==nil or stage < 6 ) then build_chest.update_needed_list( pos, stage+1 ); -- request the material for the very first building step else + -- TODO: show this update directly to the player via minetest.show_formspec( pname, formname, formspec ); meta:set_string( 'formspec', build_chest.update_formspec( pos, 'finished', player, {} )); end end @@ -856,3 +864,13 @@ minetest.register_node("handle_schematics:build", { --TODO }) +-- a player clicked on something in a formspec he was shown +handle_schematics.form_input_handler = function( player, formname, fields) + if(formname == "handle_schematics:build" and fields and fields.pos2str) then + local pos = minetest.string_to_pos( fields.pos2str ); + build_chest.on_receive_fields(pos, formname, fields, player); + end +end + +-- make sure we receive player input; needed for showing formspecs directly (which is in turn faster than just updating the node) +minetest.register_on_player_receive_fields( handle_schematics.form_input_handler ); diff --git a/mods/handle_schematics/build_chest_add_schems_by_directory.lua b/mods/handle_schematics/build_chest_add_schems_by_directory.lua index 9c80cfa..4359d64 100755 --- a/mods/handle_schematics/build_chest_add_schems_by_directory.lua +++ b/mods/handle_schematics/build_chest_add_schems_by_directory.lua @@ -79,10 +79,33 @@ end local build_chest_check_all_directories = function() -- find the name of the directory directly above the current worldpath local worldpath = minetest.get_worldpath(); + + local p = 1; + local last_found = 1; + while( last_found ) do + p = last_found; + last_found = string.find( worldpath, '/', last_found+1 ); + end + -- abort on Windows + if( p == 1 ) then + return; + end + worldpath = string.sub( worldpath, 1, p ); + +--[[ local p = 1; while( not( string.find( worldpath, '/', -1*p ))) do p = p+1; end + local found = 1; + for p=string.len( worldpath ),1,-1 do + if( p>found + and (string.byte( worldpath, p )=='/' + or string.byte( worldpath, p )=='\\')) then + found = p; + end + end +--]] worldpath = string.sub( worldpath, 1, string.len( worldpath )-p ); diff --git a/mods/handle_schematics/init.lua b/mods/handle_schematics/init.lua index b3645f4..663ecc0 100755 --- a/mods/handle_schematics/init.lua +++ b/mods/handle_schematics/init.lua @@ -41,15 +41,15 @@ dofile(handle_schematics.modpath.."/replacements_get_table.lua") -- uses build_chest.* namespace -- a chest for spawning buildings manually ---dofile(handle_schematics.modpath.."/build_chest.lua") +dofile(handle_schematics.modpath.."/build_chest.lua") -- makes the replacements from replacements_group.* available to the build chest ---dofile(handle_schematics.modpath.."/build_chest_handle_replacements.lua"); +dofile(handle_schematics.modpath.."/build_chest_handle_replacements.lua"); -- creates 2d previews of the schematic from left/right/back/front/top ---dofile(handle_schematics.modpath.."/build_chest_preview_image.lua"); +dofile(handle_schematics.modpath.."/build_chest_preview_image.lua"); -- reads a file and adds the files listed there as menu entries ---dofile(handle_schematics.modpath.."/build_chest_add_schems_from_file.lua"); +dofile(handle_schematics.modpath.."/build_chest_add_schems_from_file.lua"); -- locate schematics through directories ---dofile(handle_schematics.modpath.."/build_chest_add_schems_by_directory.lua"); +dofile(handle_schematics.modpath.."/build_chest_add_schems_by_directory.lua"); -- the main functionality of the mod; -- provides the function handle_schematics.place_building_from_file diff --git a/mods/handle_schematics/replacements_farming.lua b/mods/handle_schematics/replacements_farming.lua index 0c7e595..3763139 100755 --- a/mods/handle_schematics/replacements_farming.lua +++ b/mods/handle_schematics/replacements_farming.lua @@ -98,7 +98,7 @@ replacements_group['farming'].add_material = function( fruit, fruit_item, prefix end - if( is_loaded and mobf_trader and mobf_trader.add_trader ) then + if( is_loaded and minetest.get_modpath('mobf_trader') and mobf_trader and mobf_trader.add_trader ) then -- TODO: use replacements for the payments where needed local goods = { @@ -115,7 +115,7 @@ replacements_group['farming'].add_material = function( fruit, fruit_item, prefix fruit.."_farmer_v", goods, { "farmer" }, - "" + {'kuhhaendler.png', 'bauer_in_sonntagskleidung.png', 'baeuerin.png', 'wheat_farmer_by_addi.png', 'tomatenhaendler.png'} ); replacements_group['farming'].traders[ fruit_item ] = fruit..'_farmer_v'; diff --git a/mods/handle_schematics/replacements_wood.lua b/mods/handle_schematics/replacements_wood.lua index 113d4b6..483162c 100755 --- a/mods/handle_schematics/replacements_wood.lua +++ b/mods/handle_schematics/replacements_wood.lua @@ -127,7 +127,7 @@ replacements_group['wood'].add_material = function( candidate_list, mod_prefix, end end - if( is_loaded and mobf_trader and mobf_trader.add_trader ) then + if( is_loaded and minetest.get_modpath('mobf_trader') and mobf_trader and mobf_trader.add_trader ) then -- TODO: check if all offered payments exist local goods = { { data[3].." 4", "default:dirt 24", "default:cobble 24"}, @@ -147,7 +147,7 @@ replacements_group['wood'].add_material = function( candidate_list, mod_prefix, v.."_wood_v", goods, { "lumberjack" }, - "" + { 'holzfaeller.png' } ); replacements_group['wood'].traders[ wood_name ] = v..'_wood_v'; diff --git a/mods/mg_villages/buildings.lua b/mods/mg_villages/buildings.lua index 4f54566..a205e51 100755 --- a/mods/mg_villages/buildings.lua +++ b/mods/mg_villages/buildings.lua @@ -209,26 +209,6 @@ local buildings = { -- the hotel seems to be only the middle section of the building; it's build for another spawning algorithm -- {scm="default_town_hotel", yoff= -1, orients={1}, farming_plus=0, avoid='', typ='house', weight={taoki=1/5}}, - -- include houses from LadyMacBeth, originally created for Mauvebics mm2 modpack; the houses seem to be in canadian village style - {scm="c_bank", yoff= 1, orients={2}, farming_plus=0, avoid='', typ='shop', weight={canadian=1}, inh=-2}, - {scm="c_bank2", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='shop', weight={canadian=1}, inh=-2}, - {scm="c_bar", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='tavern', weight={canadian=1}, inh=-2}, - {scm="c_hotel", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='tavern', weight={canadian=1}, inh=-2}, - {scm="c_postoffice", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='shop', weight={canadian=1}, pervillage=1, inh=-2}, - {scm="c_bordello", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='tavern', weight={canadian=1}, pervillage=1, inh=-2}, - {scm="c_library", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='secular', weight={canadian=1}, pervillage=1, inh=-2}, - - {scm="g_observatory", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='secular', weight={canadian=1}, pervillage=1, inh=-2}, - {scm="g_court", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='secular', weight={canadian=1}, pervillage=1, inh=-2}, - {scm="g_prefecture", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='secular', weight={canadian=1}, pervillage=1, inh=-2}, - {scm="g_townhall", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='secular', weight={canadian=1}, pervillage=1, inh=-2}, - {scm="g_park2", yoff= -1, orients={0}, farming_plus=0, avoid='', typ='secular', weight={canadian=2},}, - - {scm="r_apartments", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='house_large', weight={canadian=4}, inh=20}, - {scm="r_rowhouses", yoff= 1, orients={2}, farming_plus=0, avoid='', typ='house_large', weight={canadian=4}, inh=16}, - {scm="r_manorhouse", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='house_large', weight={canadian=3}, inh=4}, - {scm="r_triplex", yoff= 1, orients={0}, farming_plus=0, avoid='', typ='house_large', weight={canadian=3}, inh=10}, - {scm="tent_tiny_1", yoff=0, orients={3}, farming_plus=0, avoid='', typ='tent', weight={tent=1, single=1}, inh=1}, {scm="tent_tiny_2", yoff=0, orients={3}, farming_plus=0, avoid='', typ='tent', weight={tent=1, single=1}, inh=1}, {scm="tent_big_1", yoff=0, orients={3}, farming_plus=0, avoid='', typ='tent', weight={tent=1, single=1}}, -- no sleeping place diff --git a/mods/mg_villages/config.lua b/mods/mg_villages/config.lua index 95db30e..e4999c2 100755 --- a/mods/mg_villages/config.lua +++ b/mods/mg_villages/config.lua @@ -32,6 +32,11 @@ mg_villages.ENABLE_PROTECTION = true; -- the first village - the one the player spawns in - will be of this type mg_villages.FIRST_VILLAGE_TYPE = 'medieval'; +-- the mapgen will disregard mapchunks where min.y > mg_villages.MAX_HEIGHT_TREATED; +-- you can set this value to 64 if you have a slow machine and a mapgen which does not create extreme mountains +-- (or if you don't care if extreme mountains may create burried villages occasionally) +mg_villages.MAX_HEIGHT_TREATED = 200; + -- choose the debug level you want mg_villages.DEBUG_LEVEL = mg_villages.DEBUG_LEVEL_NONE @@ -49,6 +54,8 @@ end -- currently not really used; does not look as good as expected mg_villages.medieval_subtype = false; +-- set this to true if you want to use normal lava - but beware: charachoal villages may cause bushfires! +--mg_villages.use_normal_unsafe_lava = false; ----------------------------------------------------------------------------- -- decrese these values slightly if you want MORE trees around your villages; diff --git a/mods/mg_villages/mapgen.lua b/mods/mg_villages/mapgen.lua index aec85d9..7b5369e 100755 --- a/mods/mg_villages/mapgen.lua +++ b/mods/mg_villages/mapgen.lua @@ -145,10 +145,35 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min local ptree = false; local old_height = maxp.y; local y = maxp.y; + + local look_for_snow = true; + if( cid.c_snow==cid.c_ignore or cid.c_snow==cid.c_air + or cid.c_ice ==cid.c_ignore or cid.c_ice ==cid.c_air ) then + look_for_snow = nil; + end + + -- if we are working on a mapchunk above, set all to air; + -- any terrain blending happens in the mapchunk below + if( minp.y > vh ) then + local air_counted = 0; + for y=minp.y, minp.y+16 do + if( data[a:index( x, y, z )] == cid.c_air ) then + air_counted = air_counted + 1; + end + end + if( air_counted > 3 or blend==0) then + for y=minp.y+15, maxp.y do + data[a:index( x, y, z)] = cid.c_air; + end + end + -- else do nothing + return; + end + -- search for a surface and set everything above target_height to air while( y > minp.y) do local ci = data[a:index(x, y, z)]; - if( ci == cid.c_snow or ci == cid.c_ice ) then + if( look_for_snow and (ci == cid.c_snow or ci == cid.c_ice or ci == cid.c_snowblock)) then has_snow = true; elseif( ci == cid.c_tree ) then tree = true; @@ -162,7 +187,7 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min -- we have found a surface of some kind surface_node = ci; old_height = y; - if( surface_node == cid.c_dirt_with_snow ) then + if( look_for_snow and surface_node == cid.c_dirt_with_snow and cid.c_dirt_with_snow~=cid.c_ignore) then has_snow = true; end end @@ -186,7 +211,7 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min if( not( surface_node ) or surface_node == cid.c_dirt) then surface_node = cid.c_dirt_with_grass; end - if( has_snow and surface_node == cid.c_dirt_with_grass and target_height > 1) then + if( look_for_snow and has_snow and surface_node == cid.c_dirt_with_grass and target_height > 1) then surface_node = cid.c_dirt_with_snow; end local below_1 = cid.c_dirt; @@ -211,7 +236,7 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min end -- do terrain blending; target_height has to be calculated based on old_height - if( target_height == maxp.y ) then + if( target_height == maxp.y and old_height < maxp.y ) then local yblend = old_height; if blend > 0 then -- leave some cliffs unblended yblend = math.floor(vh + blend * (old_height - vh)) @@ -219,7 +244,7 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min else target_height = old_height; end - for y = yblend, maxp.y do + for y = math.max( minp.y, yblend), maxp.y do if( y<=MG_VILLAGES_WATER_LEVEL ) then -- keep ice if( data[a:index( x, y, z )] ~= cid.c_ice ) then @@ -231,30 +256,33 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min end end - if( target_height < 1 ) then - -- no trees or snow below water level - elseif( tree and not( mg_villages.ethereal_trees ) and treepos) then - data[ a:index( x, target_height+1, z)] = cid.c_sapling - table.insert( treepos, {x=x, y=target_height+1, z=z, typ=0, snow=has_artificial_snow}); - elseif( jtree and not( mg_villages.ethereal_trees ) and treepos) then - data[ a:index( x, target_height+1, z)] = cid.c_jsapling - table.insert( treepos, {x=x, y=target_height+1, z=z, typ=1, snow=has_artificial_snow}); - elseif( ptree and not( mg_villages.ethereal_trees ) and treepos) then - data[ a:index( x, target_height+1, z)] = cid.c_psapling - table.insert( treepos, {x=x, y=target_height+1, z=z, typ=2, snow=has_artificial_snow}); - elseif( has_snow ) then - data[ a:index( x, target_height+1, z)] = cid.c_snow; - end - data[ a:index( x, target_height, z)] = surface_node; - if( target_height-1 >= minp.y ) then - data[ a:index( x, target_height-1, z)] = below_1; + -- only place the surface node if it is actually contained in this node + if( target_height >= minp.y and target_height < maxp.y ) then + if( target_height < 1 ) then + -- no trees or snow below water level + elseif( tree and not( mg_villages.ethereal_trees ) and treepos) then + data[ a:index( x, target_height+1, z)] = cid.c_sapling + table.insert( treepos, {x=x, y=target_height+1, z=z, typ=0, snow=has_artificial_snow}); + elseif( jtree and not( mg_villages.ethereal_trees ) and treepos) then + data[ a:index( x, target_height+1, z)] = cid.c_jsapling + table.insert( treepos, {x=x, y=target_height+1, z=z, typ=1, snow=has_artificial_snow}); + elseif( ptree and not( mg_villages.ethereal_trees ) and treepos) then + data[ a:index( x, target_height+1, z)] = cid.c_psapling + table.insert( treepos, {x=x, y=target_height+1, z=z, typ=2, snow=has_artificial_snow}); + elseif( has_snow ) then + data[ a:index( x, target_height+1, z)] = cid.c_snow; + end + data[ a:index( x, target_height, z)] = surface_node; + if( target_height-1 >= minp.y ) then + data[ a:index( x, target_height-1, z)] = below_1; + end end -- not every column will get a coal block; some may get two local coal_height1 = math.random( minp.y, maxp.y ); local coal_height2 = math.random( minp.y, maxp.y ); y = target_height-2; - while( y > minp.y and y > target_height-40 ) do + while( y > minp.y and y > target_height-40 and y <=maxp.y) do local old_node = data[a:index( x, y, z)]; -- abort as soon as we hit anything other than air if( old_node == cid.c_air or old_node == cid.c_water ) then @@ -318,7 +346,44 @@ end -- TODO: limit this function to the shell in order to speed things up -- repair mapgen griefings -mg_villages.repair_outer_shell = function( villages, minp, maxp, vm, data, param2_data, a, village_area, cid ) +mg_villages.repair_outer_shell = function( villages, minp, maxp, vm, data, param2_data, a, village_area, cid, edge_min, edge_max ) + -- find out if this part of the shell has already been generated or not + if( data[a:index(minp.x,minp.y,minp.z)] == cid.c_ignore + + and data[a:index(maxp.x,minp.y,minp.z)] == cid.c_ignore + and data[a:index(minp.x,maxp.y,minp.z)] == cid.c_ignore + and data[a:index(minp.x,minp.y,maxp.z)] == cid.c_ignore + + and data[a:index(maxp.x,maxp.y,maxp.z)] == cid.c_ignore + + and data[a:index(maxp.x,maxp.y,minp.z)] == cid.c_ignore + and data[a:index(maxp.x,minp.y,maxp.z)] == cid.c_ignore + and data[a:index(minp.x,maxp.y,maxp.z)] == cid.c_ignore ) then + + -- no - none of the edges has been created yet; no point to place anything there + return; + end + + if( minp.x < edge_min.x ) then + edge_min.x = minp.x; + end + if( minp.y < edge_min.y ) then + edge_min.y = minp.y; + end + if( minp.z < edge_min.z ) then + edge_min.z = minp.z; + end + if( maxp.x > edge_max.x ) then + edge_max.x = maxp.x; + end + if( maxp.y > edge_max.y ) then + edge_max.y = maxp.y; + end + if( maxp.z > edge_max.z ) then + edge_max.z = maxp.z; + end + + for z = minp.z, maxp.z do for x = minp.x, maxp.x do -- inside a village @@ -645,6 +710,10 @@ end -- places trees and plants at empty spaces mg_villages.village_area_fill_with_plants = function( village_area, villages, minp, maxp, data, param2_data, a, cid ) + -- do not place any plants if we are working on the mapchunk above + if( minp.y > 0 ) then + return; + end -- trees which require grow functions to be called cid.c_savannasapling = minetest.get_content_id( 'mg:savannasapling'); cid.c_pinesapling = minetest.get_content_id( 'mg:pinesapling'); @@ -692,7 +761,7 @@ mg_villages.village_area_fill_with_plants = function( village_area, villages, mi local plant_selected = false; local has_snow_cover = false; for _,v in ipairs( village.to_add_data.plantlist ) do - if( plant_id == cid.c_snow or g==cid.c_dirt_with_snow) then + if( plant_id == cid.c_snow or g==cid.c_dirt_with_snow or g==cid.c_snowblock) then has_snow_cover = true; end -- select the first plant that fits; if the node is not air, keep what is currently inside @@ -782,6 +851,7 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm, cid.c_stone = minetest.get_content_id( 'default:stone'); cid.c_dirt = minetest.get_content_id( 'default:dirt'); cid.c_snow = minetest.get_content_id( 'default:snow'); + cid.c_snowblock = minetest.get_content_id( 'default:snowblock'); cid.c_dirt_with_snow = minetest.get_content_id( 'default:dirt_with_snow' ); cid.c_dirt_with_grass = minetest.get_content_id( 'default:dirt_with_grass' ); cid.c_desert_sand = minetest.get_content_id( 'default:desert_sand' ); -- PM v @@ -834,7 +904,7 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm, if( not( village.is_single_house )) then -- only add artificial snow if the village has at least a size of 15 (else it might look too artificial) village.artificial_snow=0 - --[[ + if( not( village.artificial_snow ) and village.vs > 15) then if( mg_villages.artificial_snow_probability and math.random( 1, mg_villages.artificial_snow_probability )==1 and minetest.registered_nodes['default:snow']) then @@ -843,7 +913,7 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm, village.artificial_snow = 0; end end - ]] + -- will set village_area to N where .. is: -- 2: a building -- 3: border around a building @@ -923,10 +993,12 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm, mg_villages.flatten_village_area( villages, tmin, tmax, vm, data, param2_data, a, village_area, cid ); t1 = time_elapsed( t1, 'flatten_village_area' ); -- repair cavegen griefings and mudflow which may have happened in the outer shell (which is part of other mapnodes) - mg_villages.repair_outer_shell( villages, {x=tmin.x, y=tmin.y,z=tmin.z}, {x=tmin.x+16, y=tmax.y, z=tmax.z}, vm, data, param2_data, a, village_area, cid ); - mg_villages.repair_outer_shell( villages, {x=tmax.x-16,y=tmin.y,z=tmin.z}, {x=tmax.x, y=tmax.y, z=tmax.z}, vm, data, param2_data, a, village_area, cid ); - mg_villages.repair_outer_shell( villages, {x=tmin.x+16,y=tmin.y,z=tmin.z}, {x=tmax.x-16, y=tmax.y, z=tmin.z+16}, vm, data, param2_data, a, village_area, cid ); - mg_villages.repair_outer_shell( villages, {x=tmin.x+16,y=tmin.y,z=tmax.z-16}, {x=tmax.x-16, y=tmax.y, z=tmax.z}, vm, data, param2_data, a, village_area, cid ); + local e1 = {x=minp.x,y=minp.y,z=minp.z}; + local e2 = {x=maxp.x,y=maxp.y,z=maxp.z}; + mg_villages.repair_outer_shell( villages, {x=tmin.x, y=tmin.y,z=tmin.z}, {x=tmin.x+16, y=tmax.y, z=tmax.z}, vm, data, param2_data, a, village_area, cid, e1, e2 ); + mg_villages.repair_outer_shell( villages, {x=tmax.x-16,y=tmin.y,z=tmin.z}, {x=tmax.x, y=tmax.y, z=tmax.z}, vm, data, param2_data, a, village_area, cid, e1, e2 ); + mg_villages.repair_outer_shell( villages, {x=tmin.x+16,y=tmin.y,z=tmin.z}, {x=tmax.x-16, y=tmax.y, z=tmin.z+16}, vm, data, param2_data, a, village_area, cid, e1, e2 ); + mg_villages.repair_outer_shell( villages, {x=tmin.x+16,y=tmin.y,z=tmax.z-16}, {x=tmax.x-16, y=tmax.y, z=tmax.z}, vm, data, param2_data, a, village_area, cid, e1, e2 ); -- mg_villages.repair_outer_shell( villages, tmin, tmax, vm, data, param2_data, a, village_area, cid ); t1 = time_elapsed( t1, 'repair_outer_shell' ); @@ -959,7 +1031,8 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm, vm:set_param2_data(param2_data) t1 = time_elapsed( t1, 'vm data set' ); - vm:calc_lighting() + -- only update lighting where we actually placed the nodes + vm:calc_lighting( e1, e2 ); --minp, maxp ); --tmin, tmax) t1 = time_elapsed( t1, 'vm calc lighting' ); vm:write_to_map(data) @@ -1050,7 +1123,7 @@ minetest.register_on_generated(function(minp, maxp, seed) -- print('STRUCTURES BY MAPGEN: '..minetest.serialize( structures )); -- only generate village on the surface chunks - if( minp.y ~= -32 or minp.y < -32 or minp.y > 64) then + if( minp.y < -32 or minp.y > mg_villages.MAX_HEIGHT_TREATED) then --64 return; end diff --git a/mods/mg_villages/nodes.lua b/mods/mg_villages/nodes.lua index fe8902c..318c345 100755 --- a/mods/mg_villages/nodes.lua +++ b/mods/mg_villages/nodes.lua @@ -99,3 +99,41 @@ minetest.register_node("mg_villages:plotmarker", { end }) + +-- default to safe lava +if( not( mg_villages.use_normal_unsafe_lava )) then + local lava = minetest.registered_nodes[ "default:lava_source"]; + if( lava ) then + -- a deep copy for the table would be more helpful...but, well, ... + local new_def = minetest.deserialize( minetest.serialize( lava )); + -- this lava does not cause fire to spread + new_def.name = nil; + new_def.groups.lava = nil; + new_def.groups.hot = nil; + new_def.groups.igniter = nil; + new_def.groups.lava_tamed = 3; + new_def.description = "Lava Source (tame)"; + new_def.liquid_alternative_flowing = "mg_villages:lava_flowing_tamed"; + new_def.liquid_alternative_source = "mg_villages:lava_source_tamed"; + -- we create a NEW type of lava for this + minetest.register_node( "mg_villages:lava_source_tamed", new_def ); + end + + -- take care of the flowing variant as well + lava = minetest.registered_nodes[ "default:lava_flowing"]; + if( lava ) then + -- a deep copy for the table would be more helpful...but, well, ... + local new_def = minetest.deserialize( minetest.serialize( lava )); + -- this lava does not cause fire to spread + new_def.name = nil; + new_def.groups.lava = nil; + new_def.groups.hot = nil; + new_def.groups.igniter = nil; + new_def.groups.lava_tamed = 3; + new_def.description = "Flowing Lava (tame)"; + new_def.liquid_alternative_flowing = "mg_villages:lava_flowing_tamed"; + new_def.liquid_alternative_source = "mg_villages:lava_source_tamed"; + -- and a NEW type of flowing lava... + minetest.register_node( "mg_villages:lava_flowing_tamed", new_def ); + end +end diff --git a/mods/mg_villages/protection.lua b/mods/mg_villages/protection.lua index 22a36f5..c943901 100755 --- a/mods/mg_villages/protection.lua +++ b/mods/mg_villages/protection.lua @@ -1,4 +1,3 @@ - -- get the id of the village pos lies in (or nil if outside of villages) mg_villages.get_town_id_at_pos = function( pos ) for id, v in pairs( mg_villages.all_villages ) do @@ -42,10 +41,26 @@ minetest.is_protected = function(pos, name) if( village_id ) then local is_houseowner = false; for nr, p in ipairs( mg_villages.all_villages[ village_id ].to_add_data.bpos ) do + + trustedusers = p.can_edit + trustedUser = false + if trustedusers ~= nil then + for _,trusted in ipairs(trustedusers) do + if trusted == name then + trustedUser = true + end + end + end + -- we have located the right plot; the player can build here if he owns this particular plot if( p.x <= pos.x and (p.x + p.bsizex) >= pos.x and p.z <= pos.z and (p.z + p.bsizez) >= pos.z) then - if( p.owner and p.owner == name ) then + + -- If player has been trusted by owner, can build + if (trustedUser) then + return false; + -- If player is owner, can build + elseif( p.owner and p.owner == name ) then return false; -- the allmende can be used by all elseif( mg_villages.BUILDINGS[p.btype] and mg_villages.BUILDINGS[p.btype].typ=="allmende" ) then @@ -55,7 +70,7 @@ minetest.is_protected = function(pos, name) return true; end -- if the player just owns another plot in the village, check if it's one where villagers may live - elseif( p.owner and p.owner == name ) then + elseif( p.owner and p.owner == name or trustedUser) then local btype = mg_villages.all_villages[ village_id ].to_add_data.bpos[ nr ].btype; if( btype ~= 'road' and mg_villages.BUILDINGS[btype] @@ -73,7 +88,7 @@ minetest.is_protected = function(pos, name) return true; end return old_is_protected(pos, name); -end +end minetest.register_on_protection_violation( function(pos, name) @@ -100,96 +115,172 @@ mg_villages.plotmarker_formspec = function( pos, formname, fields, player ) -- if( not( mg_villages.ENABLE_PROTECTION )) then -- return; -- end - local meta = minetest.get_meta( pos ); if( not( meta )) then return; end local village_id = meta:get_string('village_id'); local plot_nr = meta:get_int( 'plot_nr'); - local pname = player:get_player_name(); - if( not( village_id ) or not( mg_villages.all_villages ) or not( mg_villages.all_villages[ village_id ] ) - or not( plot_nr ) or not( mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ] )) then - + if( not( village_id ) + or not( mg_villages.all_villages ) + or not( mg_villages.all_villages[ village_id ] ) + or not( plot_nr ) + or not( mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ] )) then minetest.chat_send_player( pname, 'Error. This plot marker is not configured correctly.'..minetest.serialize({village_id,plot_nr })); return; end + local owner = mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].owner; local btype = mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].btype; - local price = "default:gold_ingot 2"; - if( btype ~= 'road' - and mg_villages.BUILDINGS[btype] - and mg_villages.BUILDINGS[btype].price ) then - price = mg_villages.BUILDINGS[btype].price; - elseif( btype ~= 'road' - and mg_villages.BUILDINGS[btype] - and mg_villages.BUILDINGS[btype].typ - and mg_villages.prices[ mg_villages.BUILDINGS[btype].typ ] )then - price = mg_villages.prices[ mg_villages.BUILDINGS[btype].typ ]; - end - --determine prcie depending on building type - local price_stack= ItemStack( price ); - - local plot_descr = 'Plot No. '..tostring( plot_nr ).. ' with '..tostring( mg_villages.BUILDINGS[btype].scm); --minetest.chat_send_player( player:get_player_name(),'DATA FOR '..tostring(plot_nr)..': '..minetest.serialize( mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ] )); - local formspec = "size[8,3]".. - "label[1.0,0.5;Plot No.: "..tostring( plot_nr ).."]".. - "label[2.5,0.5;Building:]".. - "label[3.5,0.5;"..tostring( mg_villages.BUILDINGS[btype].scm ).."]".. - "field[20,20;0.1,0.1;pos2str;Pos;"..minetest.pos_to_string( pos ).."]"; - if( owner == pname and fields['abandom'] ) then - formspec = formspec.."label[0,2;You have abandomed this plot.]"; - mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].owner = nil; - meta:set_string('infotext', plot_descr ); - mg_villages.save_data(); + local original_formspec = "size[8,3]".. + "label[1.0,0.5;Plot No.: "..tostring( plot_nr ).."]".. + "label[2.5,0.5;Building:]".. + "label[3.5,0.5;"..tostring( mg_villages.BUILDINGS[btype].scm ).."]".. + "field[20,20;0.1,0.1;pos2str;Pos;"..minetest.pos_to_string( pos ).."]"; + local formspec = ""; + local ifinhabit = ""; - elseif( (not(owner) or owner=='') and fields['buy'] ) then + -- Get Price + local price = "default:gold_ingot 2"; - -- check if the price can be paid - local inv = player:get_inventory(); - if( inv and inv:contains_item( 'main', price_stack )) then - formspec = formspec.."label[0,0;Congratulations! You have bought this plot.]"; - mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].owner = pname; - meta:set_string('infotext', plot_descr..' (owned by '..tostring( pname )..')'); - -- save the data so that it survives server restart + if (btype ~= 'road' and mg_villages.BUILDINGS[btype]) then + local plot_descr = 'Plot No. '..tostring( plot_nr ).. ' with '..tostring( mg_villages.BUILDINGS[btype].scm) + + if (mg_villages.BUILDINGS[btype].price) then + price = mg_villages.BUILDINGS[btype].price; + elseif (mg_villages.BUILDINGS[btype].typ and mg_villages.prices[ mg_villages.BUILDINGS[btype].typ ]) then + price = mg_villages.prices[ mg_villages.BUILDINGS[btype].typ ]; + end + -- Get if is inhabitant house + if (mg_villages.BUILDINGS[btype].inh and mg_villages.BUILDINGS[btype].inh > 0 ) then + ifinhabit = "label[1,1.5;Owners of this plot count as village inhabitants.]"; + end + end + -- Determine price depending on building type + local price_stack= ItemStack( price ); + + + -- If nobody owns the plot + if (not(owner) or owner=='') then + + formspec = original_formspec .. + "label[1,1;You can buy this plot for]".. + "label[3.8,1;"..tostring( price_stack:get_count() ).." x ]".. + "item_image[4.3,0.8;1,1;"..( price_stack:get_name() ).."]".. + ifinhabit.. + "button[2,2.5;1.5,0.5;buy;Buy plot]".. + "button_exit[4,2.5;1.5,0.5;abort;Exit]"; + + -- On Press buy button + if (fields['buy']) then + local inv = player:get_inventory(); + + if not mg_villages.all_villages[village_id].ownerlist then + mg_villages.all_villages[village_id].ownerlist = {} + end + + -- Check if player already has a house in the village + if mg_villages.all_villages[village_id].ownerlist[pname] then + formspec = formspec.."label[1,1.9;Sorry. You already have a plot in this village.]"; + + -- Check if the price can be paid + elseif( inv and inv:contains_item( 'main', price_stack )) then + formspec = original_formspec.. + "label[1,1;Congratulations! You have bought this plot.]".. + "button_exit[5.75,2.5;1.5,0.5;abort;Exit]"; + mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].owner = pname; + if mg_villages.all_villages[village_id].ownerlist then + mg_villages.all_villages[village_id].ownerlist[pname] = true; + else + mg_villages.all_villages[village_id].ownerlist[pname] = true; + end + meta:set_string('infotext', 'Plot No. '..tostring( plot_nr ).. ' with '..tostring( mg_villages.BUILDINGS[btype].scm)..' (owned by '..tostring( pname )..')'); + -- save the data so that it survives server restart + mg_villages.save_data(); + -- substract the price from the players inventory + inv:remove_item( 'main', price_stack ); + else + formspec = formspec.."label[1,1.9;Sorry. You are not able to pay the price.]"; + end + end + + -- If player is the owner of the plot + elseif (owner==pname) then + + -- Check if inhabitant house + if(btype ~= 'road' + and mg_villages.BUILDINGS[btype] + and mg_villages.BUILDINGS[btype].inh + and mg_villages.BUILDINGS[btype].inh > 0 ) then + + ifinhabit = "label[1,1.5;You are allowed to modify the common village area.]"; + end + + formspec = original_formspec.."size[8,3]".. + "label[1,1;This is your plot. You have bought it.]".. + "button[0.75,2.5;3,0.5;add_remove;Add/Remove Players]".. + ifinhabit.. + "button_exit[3.75,2.5;2.0,0.5;abandon;Abandon plot]".. + "button_exit[5.75,2.5;1.5,0.5;abort;Exit]"; + + -- If Player wants to abandon plot + if(fields['abandon'] ) then + formspec = original_formspec.. + "label[1,1;You have abandoned this plot.]".. + "button_exit[5.75,2.5;1.5,0.5;abort;Exit]"; + mg_villages.all_villages[village_id].ownerlist[pname] = nil; + mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].can_edit = {} + mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].owner = nil; + -- Return price to player + local inv = player:get_inventory(); + inv:add_item( 'main', price_stack ); + meta:set_string('infotext', 'Plot No. '..tostring( plot_nr ).. ' with '..tostring( mg_villages.BUILDINGS[btype].scm) ); mg_villages.save_data(); - -- substract the price from the players inventory - inv:remove_item( 'main', price_stack ); - else - formspec = formspec.."label[0,0;Sorry. You are not able to pay the price.]"; end - end - -- update the owner information - owner = mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].owner; + -- If Player wants to add/remove trusted players + if (fields['add_remove']) then + local previousTrustees = mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].can_edit + local output = ""; + if previousTrustees == nil then + previousTrustees = {} + else + for _, player in ipairs(previousTrustees) do + output = output..player.."\n" + end + end + formspec = "size[8,3]".. + "field[20,20;0.1,0.1;pos2str;Pos;"..minetest.pos_to_string( pos ).."]".. + "textarea[0.3,0.2;8,2.5;ownerplayers;Trusted Players;"..output.."]".. + "button[3.25,2.5;1.5,0.5;savetrustees;Save]"; - if( owner == pname ) then - formspec = formspec.."label[1,1;This is your plot. You have bought it.]".. - "button_exit[2,2.5;2.0,0.5;abandom;Abandom plot]".. - "button_exit[4,2.5;1.5,0.5;abort;Exit]"; - elseif( not( owner ) or owner=="" ) then - formspec = formspec.."label[1,1;You can buy this plot for]".. - "label[3.8,1;"..tostring( price_stack:get_count() ).." x ]".. - "item_image[4.3,0.8;1,1;"..( price_stack:get_name() ).."]".. - "button_exit[2,2.5;1.5,0.5;buy;Buy plot]".. - "button_exit[4,2.5;1.5,0.5;abort;Exit]"; + mg_villages.save_data() + end + + -- Save trusted players + if (fields["savetrustees"] == "Save") then + + if not mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].can_edit then + mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].can_edit = {} + end + + local x = 1; + for _, player in ipairs(fields.ownerplayers:split("\n")) do + mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].can_edit[x] = player + x = x + 1 + end + + mg_villages.save_data(); + end + + -- If A different Player owns plot else - formspec = formspec.."label[1,1;"..tostring( owner ).." owns this plot.]".. - "button_exit[3,2.5;1.5,0.5;abort;Exit]"; - end - - if( btype ~= 'road' - and mg_villages.BUILDINGS[btype] - and mg_villages.BUILDINGS[btype].inh - and mg_villages.BUILDINGS[btype].inh > 0 ) then - if( owner==pname ) then - formspec = formspec.."label[1,1.5;You are allowed to modify the common village area.]"; - else - formspec = formspec.."label[1,1.5;Owners of this plot count as village inhabitants.]"; - end + formspec = original_formspec.."label[1,1;"..tostring( owner ).." owns this plot.]".. + "button_exit[3,2.5;1.5,0.5;abort;Exit]"; end minetest.show_formspec( pname, "mg_villages:plotmarker", formspec ); @@ -198,6 +289,7 @@ end mg_villages.form_input_handler = function( player, formname, fields) + mg_villages.print(mg_villages.DEBUG_LEVEL_NORMAL,minetest.serialize(fields)); if( not( mg_villages.ENABLE_PROTECTION )) then return false; end diff --git a/mods/mg_villages/replacements.lua b/mods/mg_villages/replacements.lua index fc00ed7..a8f8d1a 100755 --- a/mods/mg_villages/replacements.lua +++ b/mods/mg_villages/replacements.lua @@ -467,61 +467,6 @@ mg_villages.replacements_lumberjack = function( housetype, pr, replacements ) end -mg_villages.replacements_canadian = function( housetype, pr, replacements ) - - table.insert( replacements, {'4seasons:slimtree_wood', 'default:fence_wood'}); - if( true) then return replacements; end -- TODO - -- remove inner corners, wallpapers etc. - local to_air = { 38, 36, 68, 66, 69, 67, 77, 47, 44, 43, 37, 75, 45, 65, 71, 76, 46 }; - for _,v in ipairs( to_air ) do - table.insert( replacements, {'hdb:'..tostring( v )..'_ic', 'air' }); - end - - to_air = { 49, 50, 52, 72, 73, 74 }; - for _,v in ipairs( to_air ) do - table.insert( replacements, {'hdb:'..tostring( v )..'_edge', 'air' }); - end - - to_air = { 49, 50, 52, 72, 73, 74 }; - for _,v in ipairs( to_air ) do - table.insert( replacements, {'hdb:'..tostring( v )..'_edgeic', 'air' }); - end - - -- thin slabs for covering walls - to_air = { 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 76, 77 }; - for _,v in ipairs( to_air ) do - table.insert( replacements, {'hdb:'..tostring( v ), 'air' }); - end - - -- these contain the majority of nodes used (junglewood is too dark) - local materials = {'default:wood', 'default:pinewood', 'mg:pinewood', 'mg:savannawood', - 'default:clay', 'default:brick', 'default:sandstone', - 'default:stonebrick', 'default:desert_stonebrick','default:sandstonebrick', 'default:sandstone','default:stone','default:desert_stone', - 'default:coalblock','default:steelblock'}; - --- local change_groups = { {49, 16, 29, 33, 82, 8}, {19, 4, 83, 2}, { 5, 80, 35, 36, 3}, {10, 31}, {28, 78}, { 6, 52, 1}, {7}}; - local change_groups = { {16, 29, 33, 82, 8}, {19, 4, 83, 2}, { 5, 80, 35, 3}, {10, 31}, {28, 78, 27}, { 6, 1}, {7}, {30,25,81,79},{64}}; - for _,cg in ipairs( change_groups ) do - - local m1 = materials[ pr:next( 1, #materials )]; - for j,v in ipairs( cg ) do - table.insert( replacements, {'hdb:'..tostring( v ), m1 }); - end - end - - -- hdb:9_lh and hdb:86_lh are slabs - local materials_slab = {'stonebrick', 'stone', 'sandstone', 'cobble' }; - local slab_group = {33,58}; - for _, c in ipairs( slab_group ) do - local ms = materials_slab[ pr:next( 1, #materials_slab )]; - table.insert( replacements, { 'hdb:'..tostring(c)..'_lh', 'stairs:slab_'..ms }); - table.insert( replacements, { 'hdb:'..tostring(c), 'default:'..ms }); - end - - return replacements; -end - - mg_villages.replacements_logcabin = function( housetype, pr, replacements ) -- for logcabins, wood is the most likely type of roof material @@ -943,6 +888,13 @@ mg_villages.get_replacement_table = function( housetype, pr, replacements ) end -- it is very problematic if the torches on houses melt snow and cause flooding; thus, we use a torch that is not hot table.insert( replacements, {'default:torch', 'mg_villages:torch'}); + + -- make charachoal villages safe from spreading fire + if( not( mg_villages.use_normal_unsafe_lava )) then + table.insert( replacements, {'default:lava_source', 'mg_villages:lava_source_tamed'}); + table.insert( replacements, {'default:lava_flowing', 'mg_villages:lava_flowing_tamed'}); + end + for i,v in ipairs( replacements ) do if( v and #v == 2 ) then rtable[ v[1] ] = v[2]; @@ -1002,11 +954,7 @@ mg_villages.get_fruit_replacements = function( replacements, fruit) -- this is mostly used by the voxelmanip based spawning of .we files replacements.ids[ minetest.get_content_id( old_name )] = minetest.get_content_id( new_name ); -- this is used by the place_schematic based spawning - for i,v in ipairs( replacements.table ) do - if( v and #v and v[1]==old_name ) then - v[2] = new_name; - end - end + replacements.table[ old_name ] = new_name; end end end diff --git a/mods/mg_villages/schems/baking_house_1.mts b/mods/mg_villages/schems/baking_house_1.mts index b79494429bbb23f7c61affd9df96951774431dc5..fa459c6cce73df948121f583c2f85fcb6880f787 100755 GIT binary patch delta 668 zcmX@kew;(nHze4XfrWvSft!J+9swBSH%d4#8VM%nmy{%?rxsgfB<7{$X6EED@TH`t zC6?xtSmh+9q@)%x@WGXoBqrsgPA+H65fVnIDNBqm&Mz&R{E<<-oJ2zz~8%u}$Y~#I_&r10TlZydte-C73W?^+~bUJ2ra&BQ`WdIX%bYW?7b2@W$ zVQF$-V{c+&Y-MfUJ(t>e%(+;$0%1*4wG`St%Gz=cn>OFo~gtRw-jn@}4qe9Q4X>$D zcG+d3+`guW_Z7giALyO{)JL1)RU`cVDVopHc>Ehg4hL)%k@XB@<3L9*XGb4=rgVMZ z2hPT6tq9p=&Tay-VJ`|%29f)OOa_>njqtN&q*8=z7C{bPgb;F_A`n>zc>x(B=M*B4 v)B1em7-{JdFh!UL$aY56jUpDTXAz}E?EHGZhrEz<^k5!DFM#$3hW|!y9vTVu diff --git a/mods/mg_villages/schems/baking_house_2.mts b/mods/mg_villages/schems/baking_house_2.mts index b79494429bbb23f7c61affd9df96951774431dc5..cf9fde8a75fb3ce67b3d5a7698544a48994b2183 100755 GIT binary patch delta 825 zcmX@kKAY3hHze4XfrWvSftP`&9vLtwG4Q0MrX`l)#e^HOp%b8;B?;6h2MdC3_J{0M$xQBi8nM7NTOr=kS~ic1nRi;As^ za}tx{LB>zEVANtQ&PdHko1D(5Ad4`jBoSyC0}tGolG3EfD;TZ4MPSY;Pb^6-iZ9MD zElN&h5P+*IPb|*J%u8qBhp9^|Ey_y-DiMYWJ2AcX8#i0>=ryq(5fd`N+(fjQ#suB(2zcQ4!4z5Ms$ns*6#~SrEWg@7_vX3|7h){HCN@G80Dnvy_OvMx5V`9 zsYFgzo8-u(*`IV$C_4oFqyaiVZm0}-c#cmMs@v>2! zCiHZWZP8 z)QYKRJH5?t``OCyU*;!OCi@tjyvoYQeb>skR`%3e=3h}$0>#hnj#(2|#uhL5qwl~1 zNhu?~SvS{QU!W%_|0PZ!JvC^W>SVQRT$xN^&1!#HN?$eXm27wPmcKH)`hMK4<2P0s z%3R@Pr}>CCqN+RWMmy(*6 zSejE}m7JfHlr!;ftgujVNn&PEu~l(SVp2R*XQbw&O}@@(&BqTjIjyuPFL81#lX!i_oVVextC|&fc(g%vpm)U@DbwEG4cZ&-SQ~CHzozTncl`~6@4?#{|6&;Lu}fKm zFOk2)zFvy&!9(HM#|w9)^)6Q4KFh+y9Z`s$} zp2U2L>Fx-TZY|ce*e+e{S7|om_LKOm#R*Gn>QnEwZEi}moqnt0%+82ykJq^5vYfj= z<#~uS>*9GQet!M0aG=$HtGC_!)oWCzi~dRYJhNGS_VYc*>+h)h&bemwy2+*P(>$XT znJ=eub0$~Y$*nK-uWbEXcxmgjOYU>lThvdx%KNo^dTiOv)J1ppE$jF$dSJ8si+K!J z+-E-wRsQo&bJqDw6@R2%_}FtqCw}EgdF?=D}ntfcln`?+J8YdLPFp37s}l&H@Y z$TsnJix1n3*}We&r!EO{YRM6E;ZL}|k1Uo}r8GG7WBxXxfd lQRa5FS4nJ5y5LgRH-D=3weOiw@+CpeMZe)2d)t4vd;qNz9eDr% diff --git a/mods/mg_villages/schems/baking_house_3.mts b/mods/mg_villages/schems/baking_house_3.mts index 3787467d941eaca060a9310f96678ca73f769c31..1ccfc0be11fd30db2959ef22dfa07e19c1f33411 100755 GIT binary patch delta 707 zcmZ3%v5iyGHze4XfrWvSft!J^9sw9sCQ2BIiln5bC6?xtSd}N1q!z^&=a&{Gr%v=# z6ck9#FDXe(Pb~(@6lY}SrEkpCWfT&Gi)JL|rQ~MjE*SgphdGbK4cDJdtFK^Vr* zNi0hQ8#>vBNur(?CR|*SpO?zO596kl7Ud--r!oi?mn3Eu6SOCSefb^3<`m^s>oc=`NWP;dj$wuABJIuE`9` zV{n*g(6GbNuRibuhbyOYPI>3o8P%=1Ou;*jKRc$iDLBynU!tF*)KML6u4*w+n*+)j zkGj@qRWw=liLD9zab=!%*Q!1f)AwO9=>f#>#p6y2J5 z_E`9p(uEfUxr)V-&(ud0u35B>*HxxCDsX$#qNenDwI4-O1NJ!0>w5L*E!&MMwtsss z*zlE4zR0mYaLGlJYj*n|E-MY(b$k2o*=7$I`VSrX?N-QsuaMhv>tl=ig~huhOX36H z9}#PvD%=Zl(D7u?5zgtp{9U~1ZKOuU^DC`84zRw}-IFoxn#L8j z)+6U8)NtGLB4nb@Xs z2LHKnc&WQ^=)BNC&7Dhs-s?^&-roD5w^z+0GB%~_=H)s6j(NvCEh}`WjHzMPJ#}6b E0B$}xMgRZ+ delta 564 zcmV-40?Ylj38)AdO;l4&00RIC015yO|NsC0|NsC0|Nj6Vkr^_PVIZ-SECG|!0eUP9 zWMyVyb!>DxWNC7A01jkjW?^+~bUI^iVq$D%01sqkW?^+~bUJ2ra&BRhZUPv85_5E6 zX>xNqb8KN^Ut@1#Vr*r2ob6W)bHX4D4bbAW8=KYY=H~wYzuW>1G~mZ{(COV8j*`5F z=QE951ppBZ0D1T0v}Oer&N#cKRpXq&1I%&yShGCM*80djo$xNQH8=1GPhi|=Tvh|m z@Pg5j5RF$8M&mTJ3~7nIr9CZw`@}Yh%V;*??uz^r(Rf`GvPQqxyn+tb4p*;9Cu{F_ zBh=Zjp75HxfGqK8pVI8V*Llt3^oH$aJ7nk$pWlVv*buS_y>Uy;hH18SuCcbmj&r?n zTg_Zy+#C0)xq&U+eGR=~HNQcb-pKzA0_@=3jh&17TK33rURdNKAle~+#>FPoZaC|_ zCV&2wKI^RY3L$8ggz(HgP5zAcNiF&G*y5nh`Mr^&`Lnp59L;--_fe*adS&PZonU{Z zncJm1$2k)&7+;f3HrZtVz>b{HW0=4(#R1+7&FW3 znVm`I2z-A9oXD(ds70bzxxSoPMUGIM*#Yp&YA8jlZk4tg9XeZ;%?wKR1s--3(wtPI zAhYsURpBc_Wp|vdMs;0paPvE|`#IwDyCv~iWbjHb=P3-PJVt7g9uzEBe5hoBfhvKH8qDp7-m9FVp$^0Ny5b?iJ3*k zR$wYVIX@{WCzU}6CYY0$1QX+j=}s#x%1ca6t*D>#HnMTnWCI?*=z{Ic`Q}IFT8Y*M z#ot|$>BOD$VmZ6?^*tGdY%WzMo{cdqvO3h8OF< zE&jH5T7O)%PnB=x%M}mr9@|!G(fxQ$lhnP#!qY-cn%1ya_^lCrBoV+`{kZzuiVKIn zN!e9!Pwl<8xc=fi-$#kYiOIijY!gdY(XBbMxoz_MVyE6$*XD0M7P+=uaa|mfhq(6C z`2sPY)9?KLC^LDtW68#^{~qzw%(?ncrs$Z@sT=c7X3ycQI(Mum=F+?7&F2NvrxvM2 zo(SvQ>@{;qjmS9*^XU7N=XI*PJX}A^K&wv3s6Srd`{|iSA~_#h)W5Fu-a5V0LiyZ0 zp>r+spL4ps>)yQi_zdIU=jUwQQSVb&c0(q8((L$yYQGotelan>X?Di4SSyE=JQ)c|%Nd9giR zd?)eu`z=cKha<(O8rCWNTK%@JzI@i>H|j}eBqN_&+}2xHe68~KjJbJ-zLgp1W>=S9 z{xMb6dzwzVJo_nmK!~ zRi~}Y6g=NoAYkO7+sHTT(pHUQAKu(^eii1_>HdM|YWOpqPdu{QH?B3)f!KN`ED3F}F_ge8RcS?OSb(=d@kS`lVTE zs;SSrA$`k&w3An5JhndHb)Mn>{r$13%t;qDgU+Y81z-5Qonzj@T?*++dzK}dR-ccE jox1tRl7Bio+0RsOTlS!Ci}2mJUxjbip3Ya@^P>v@Y%r{H delta 745 zcmZ3@HI-A+Hze4Xfti6D2nGHl0E6sA8Ka3a<5*HMi%K@W@0vF3jEJ@CYFD^+<&0!EOE=kNRDz*Ys@yYo~Nja$u{3)qviKRIuR%xY0 zd5OuX3_>tfIf+S7MHO@2M)1y_ZNQ=Cx%X9-`T4E8@80?M|Nb2X7L_dfvddZTCvIOh z#pMI*tSrWWIgH)^>yP~4c%0zYExYJ<2+uQa+4+mUO<5~-`P1fK_u97Ime|cxeRxL; z*S-Uc$1lxsyp~>Za*gVvY^RxTN@H#=bm6|OUC}EhmHjpF^(m{}hpLVo`?m0{a?j3F zyfudxHzmguyY$|hT@e!X*lVxArAL@tVZ?1m2{jqLneMPSI^n%^3h1~lE-uCveX8$e~%KK@1eYfOa zR_)SF6%qesIZp34$UB?yQTpQgvlUyX?L9rG`(sq$%tGm0=e)NaZvzeVyyLI-{MdX_ zZFbHkAfcm|{?1|Al-L^8xu!pZCFgH-;m_h%$ZpapUKK0;eyx;!#oU6-OUDn)Teghj zPW=PtfJIJOj9--cAGSP_vF;alIQ@Z>DPFT6@Q-@3aD=`(zYgDW-_kRQ0aI_7S_CEd z|5sow;Co(p?)QT5S86K?4P>W0S<+)_!1A?j{(+}CjkV7emswRk2?=($esEw)u6gdN zwKA(*yk?(ne3>=jz~!2L>p=d>gu)kPTh_h_N(fP3o~(0-(|_eVrp;FBkIyW5sCH-P ZI`(;i1(WY|zdLVhW54YWYuDuUHvx)^Y~la_ diff --git a/mods/mg_villages/schems/mill_1.mts b/mods/mg_villages/schems/mill_1.mts index 0f44e59663ed6bea841aeca74631775bdbbbe3c2..a04110b701d56c979654f63c41fdab795113cac9 100755 GIT binary patch delta 541 zcmV+&0^DxV{c+&Y-Io#V{deHVP|D?I&^4qWpik0 zZf9R+Y;SLJ01aeiW?^+~bUJiza${%!3}j_yVRdYDI%H{bbdiF~f1B%agCG!v5hR*w zFF*Reef6q|R&EOf#7ob2CNt4>7lLP2O(u+yRM1mAAqwe&>%s)r<+0QSy0756oVrS{lN(ot>vGD*jdYzL>ooym#-72J-5141B^j+&QQKVT+_yz=U7X6g z?h%c1UCTP+?6<4;e|B%s(XnPXjbP8AbER^Wsy|QCXW&0-^w>>t+-eX*o<~)iuf}{q^s9=!Gs+vBh<3yNj;PGp$1t`n%AYS+ zj~%1jQTcOG%C&p1XsXKey4hE*sM@nk`L2UsLw#4zxlb|af9+;;)a6NcZs_&*jL}r( za$TygXocQ=nK2ohOW*a;_jUB_kLjGFxsEwp*KInJG^Iboy4E@585W9DjO(r~d^b`~ zaNR7puAJbyS#VuB!F99Xx?=hP0000000000001C2p07Fq07u97g9Ru?z1hJRqb4_b zxrv+(PHx6xNB;Hdu;^{BGWwpegLCEcdDqIf8twvmL=5;wI~K-T`Q|UQt(V&wA9*!- f7oyjSsuel%+184EXRRhTI~V`}z{dOnaLz#_n@bI( delta 477 zcmV<30V4jZ289NYA^{MQBQueJ9S;sWs#iAf0^l$gCG!u5j+yz z>1=ocMuFEO7E=+J; zPF=-yV&}?mT~67kN!K-Gy*6OZ*elqv+oIU0AfwePYFi7PdtU_C#i^|89?>}0b*v|@ zez$sW_XZu6HT!7>e|rv{E0j^H{yj-wfp?VjSgkm&UY#4XF3?P#YZm7TWkfr*>QPt)vncooos$w6E@&+fO{dm47Ds%QZ&TWhG=gZY&Wt2NAe=SP6 zcfTr{sxrN9_LVED_AFDr`{4Ij-_>(&Q%rcf869EB^p`yBEe7K&4h>#i;QHd0P--7L7SoZz}y za9ugUb+h2QV)_LD000000000003bJ>pE>~m00dI|hin{tF>3OVms`l`;N)Q}A}zfn z`v0<(@kgz3JA!lN^Lh8mw;S#PdPI!)W;+(fUisE9w4=@Kj7zpAzl7+$qH0CXe73z} TKUu3ayA1{a0I)NE``|!IpuOiO diff --git a/mods/mg_villages/village_types.lua b/mods/mg_villages/village_types.lua index 6af0912..84c5e94 100755 --- a/mods/mg_villages/village_types.lua +++ b/mods/mg_villages/village_types.lua @@ -39,8 +39,6 @@ local village_type_data_list = { replacement_function = mg_villages.replacements_claytrader }, logcabin = { min = 15, max = 30, space_between_buildings=1, mods={'cottages'}, texture = 'default_wood.png', replacement_function = mg_villages.replacements_logcabin }, - canadian = { min = 40, max = 110, space_between_buildings=1, mods={'hdb','nbu'}, texture = 'wool_white.png', - replacement_function = mg_villages.replacements_canadian }, grasshut = { min = 10, max = 40, space_between_buildings=1, mods={'dryplants'}, texture = 'dryplants_reed.png', replacement_function = mg_villages.replacements_grasshut }, tent = { min = 5, max = 20, space_between_buildings=2, mods={'cottages'}, texture = 'wool_white.png', name_preifx = 'Tent at', diff --git a/mods/mg_villages/villages.lua b/mods/mg_villages/villages.lua index 90b5879..14d9dac 100755 --- a/mods/mg_villages/villages.lua +++ b/mods/mg_villages/villages.lua @@ -189,7 +189,7 @@ mg_villages.road_nr = 0; local function generate_road(village, l, pr, roadsize_list, road_materials, rx, rz, rdx, rdz, vnoise, space_between_buildings, iteration_depth) local roadsize = math.floor(roadsize_list[ iteration_depth ]/2); - if( not( roadsize )) then + if( not( roadsize ) or roadsize==0) then roadsize = mg_villages.FIRST_ROADSIZE; end local roadsize_a = roadsize; @@ -366,7 +366,7 @@ local function generate_road(village, l, pr, roadsize_list, road_materials, rx, rxmax = rxmax+1; end end - l[#l+1] = {x = rxmin, y = vh, z = rzmin, btype = "road", + l[#l+1] = {x = rxmin+1, y = vh, z = rzmin, btype = "road", bsizex = rxmax - rxmin + 1, bsizez = rzmax - rzmin + 1, brotate = 0, road_nr = mg_villages.road_nr} if( road_materials and road_materials[ iteration_depth ] and minetest.registered_nodes[ road_materials[ iteration_depth ]] ) then l[#l].road_material = minetest.get_content_id( road_materials[ iteration_depth ] ); @@ -456,7 +456,7 @@ local function generate_bpos(village, pr, vnoise, space_between_buildings) -- the function below is recursive; we need a way to count roads mg_villages.road_nr = 0; local roadsize_list = {}; - for i=1,mg_villages.FIRST_ROADSIZE do + for i=1,mg_villages.FIRST_ROADSIZE*2 do roadsize_list[i] = i; end if( mg_villages.village_type_data[ village.village_type ].roadsize_list ) then