mg_villages/roads.lua

129 lines
4.8 KiB
Lua

-- pos needs to be a position either on a road or at max 1 node away from a road
mg_villages.get_path_from_pos_to_plot = function( village_id, pos, target_plot_nr )
if( not( mg_villages.all_villages[ village_id ] )
or not( target_plot_nr )
or not( mg_villages.all_villages[ village_id ].to_add_data.bpos[ target_plot_nr ])
or not( mg_villages.all_villages[ village_id ].to_add_data.bpos[ target_plot_nr ].road_nr)) then
return {};
end
local bpos_list = mg_villages.all_villages[ village_id ].to_add_data.bpos;
-- find out which road is the one next to pos
local standing_on_road = nil;
local roads = mg_villages.get_road_list( village_id );
for i,road in ipairs( roads ) do
local r = bpos_list[ road ]; -- road data
-- if this is really a road, and if a parent road exists (or is 0)
if( r and r.btype == "road" and r.parent_road_plot
-- ..and pos is in the area of the road or next to it
and pos.x >= r.x-1 and pos.x <= r.x + r.bsizex + 1
and pos.z >= r.z-1 and pos.z <= r.z + r.bsizez + 1
and pos.y >= r.y-4 and pos.y <= r.y + 4 ) then
standing_on_road = i;
end
end
-- nothing found
if( not( standing_on_road )) then
return;
end
-- walk from pos up to the main road
local start_to_main_road = {};
local next_road_plot = roads[ standing_on_road ];
while( next_road_plot and bpos_list[ next_road_plot ] and bpos_list[ next_road_plot ].btype=="road" ) do
table.insert( start_to_main_road, next_road_plot );
next_road_plot = bpos_list[ next_road_plot ].parent_road_plot;
end
-- walk from the target road up to the main road - until we find a road that is
-- already part of the path from pos to the main road
local target_to_main_road = {};
local next_road_plot = roads[ bpos_list[ target_plot_nr ].road_nr ];
local match_found = -1;
while( next_road_plot and bpos_list[ next_road_plot ] and bpos_list[ next_road_plot ].btype=="road" and match_found==-1) do
-- it may not be necessary to go all the way back to the main road
for i,r in ipairs( start_to_main_road ) do
if( r == next_road_plot ) then
match_found = i;
end
end
if( match_found == -1) then
table.insert( target_to_main_road, next_road_plot );
end
next_road_plot = bpos_list[ next_road_plot ].parent_road_plot;
end
-- combine the full walk through the tree-like road structure into one list of roads
for i,r in ipairs( target_to_main_road ) do
table.insert( start_to_main_road, r );
end
-- translate the roads into positions
minetest.chat_send_player("singleplayer","roads to walk on: "..minetest.serialize( start_to_main_road));
end
-- try to reconstruct the tree-like road network structure (the data was
-- not saved completely from the beginning)
mg_villages.get_road_list = function( village_id )
if( not( mg_villages.all_villages[ village_id ] )) then
return {};
end
local bpos_list = mg_villages.all_villages[ village_id ].to_add_data.bpos;
local roads = {};
for i,pos in ipairs( bpos_list ) do
if( pos.btype and pos.btype=="road" ) then
-- store the plot nr for each road nr
roads[ pos.road_nr ] = i;
-- store weather the road streches in x- or z-direction
if( pos.bsizex >= pos.bsizez) then
pos.xdir = true;
else
pos.xdir = false;
end
end
end
-- the parent roads have already been identified
if( bpos_list[ roads[ 1 ]].parent_road_plot == 0 ) then
return roads;
end
-- assume that road nr. 1 is the main road (which it is due to the way villages are constructed)
bpos_list[ roads[ 1 ]].parent_road_plot = 0;
-- identify all parent roads
for i=1,#roads do
if( bpos_list[ roads[i] ].parent_road_plot ) then
mg_villages.mark_roads_that_branch_off( bpos_list, roads, roads[i] );
end
end
return roads;
end
-- changes bpos_list and sets bpos_list[ road ].parent_road_plot = plot_nr for those roads where
-- plot_nr contains the road from which road branches off
mg_villages.mark_roads_that_branch_off = function( bpos_list, roads, plot_nr )
-- see which roads branch off from this parent road
local parent_road = bpos_list[ plot_nr ];
for i,road in ipairs( roads ) do
local r = bpos_list[ road ]; -- road data
-- if the road is not yet connected to another one
if( r.parent_road_plot == nil
-- and if it is 90 degree rotated compared to the potential parent road
and( r.xdir ~= parent_road.xdir )
-- and if one end lies inside the parent road
and( (r.x >= parent_road.x and r.x <= parent_road.x + parent_road.bsizex)
or(r.x+r.bsizex >= parent_road.x and r.x+r.bsizex <= parent_road.x + parent_road.bsizex))
and( (r.z >= parent_road.z and r.z <= parent_road.z + parent_road.bsizez)
or(r.z+r.bsizez >= parent_road.z and r.z+r.bsizez <= parent_road.z + parent_road.bsizez))) then
-- store plot_nr instead of road_nr as that is more useful
bpos_list[ road ].parent_road_plot = plot_nr;
end
end
end