2014-08-04 22:18:20 +02:00
minetest.register_privilege ( " mg_villages " , { description = " Allows to teleport to villages via /vist <nr> " , give_to_singleplayer = false } ) ;
2017-07-24 18:21:32 +02:00
-- store per player which list of villages was offered
mg_villages.tmp_player_village_list = { } ;
-- list all plots of a village:
-- plot_nr, type of building, #inhabitants, occupation, name
mg_villages.list_plots_formspec = function ( player , formname , fields )
if ( not ( player ) or fields.quit or not ( fields.village_id ) or not ( mg_villages.all_villages [ fields.village_id ] ) ) then
return
end
local pname = player : get_player_name ( ) ;
-- analyze the road network (this has not been done from the beginning..)
2017-07-24 21:08:26 +02:00
mg_villages.get_road_list ( fields.village_id , false ) ;
2017-07-24 18:21:32 +02:00
2017-07-26 04:30:32 +02:00
-- allow to click through the villages using prev/next buttons
local liste = mg_villages.tmp_player_village_list [ pname ] ;
local prev_next_button = " button[8.5,11.6;1,0.5;back_to_villagelist;Back] " ;
if ( liste and # liste > 1 and liste [ 1 ] ~= fields.village_id ) then
prev_next_button = prev_next_button .. ' button[9.5,11.6;1,0.5;prev;Prev] ' ;
end
if ( liste and # liste > 1 and liste [ # liste ] ~= fields.village_id ) then
prev_next_button = prev_next_button .. ' button[10.5,11.6;1,0.5;next;Next] ' ;
end
2017-07-24 18:21:32 +02:00
local formspec = ' size[12,12] ' ..
' field[20,20;0.1,0.1;village_id;VillageID; ' .. minetest.formspec_escape ( fields.village_id ) .. " ] " ..
2017-07-24 18:56:39 +02:00
' button_exit[4.0,1.0;2,0.5;quit;Exit] ' ..
' button[9.5,1.0;3,0.5;back_to_villagelist;Back to village list] ' ..
2017-07-26 04:30:32 +02:00
prev_next_button ..
2017-07-24 18:21:32 +02:00
' tablecolumns[ ' ..
' text,align=right; ' .. -- plot nr
' text,align=center; ' .. -- type of building
' text,align=center; ' .. -- amount of inhabitants
' text,align=center; ' .. -- occupation of first inhabitant
' text,align=center; ' .. -- name of first inhabitat
' text,align=center] ' .. -- comment
' table[0.1,2.0;11.4,8.8; ' .. formname .. ' ; ' ..
' PlotNr,Type of building, ' .. minetest.formspec_escape ( ' #Inhab. ' ) ..
' ,Job,Owner,Comment, ' ;
local bpos_list = mg_villages.all_villages [ fields.village_id ] . to_add_data.bpos ;
for plot_nr , bpos in ipairs ( bpos_list ) do
formspec = formspec .. plot_nr .. ' , ' ;
if ( bpos.btype and bpos.btype ~= " road " and mg_villages.BUILDINGS [ bpos.btype ] ) then
formspec = formspec .. mg_villages.BUILDINGS [ bpos.btype ] . typ .. ' , ' ;
else
formspec = formspec .. tostring ( bpos.btype ) .. ' , ' ;
end
if ( not ( bpos.beds ) or # bpos.beds < 1 ) then
2017-07-24 19:17:01 +02:00
if ( bpos.worker and bpos.worker . lives_at and bpos_list [ bpos.worker . lives_at ]
and bpos_list [ bpos.worker . lives_at ] . beds
and bpos_list [ bpos.worker . lives_at ] . beds [ 1 ] ) then
2017-07-24 18:21:32 +02:00
local btype2 = mg_villages.BUILDINGS [ bpos_list [ bpos.worker . lives_at ] . btype ] ;
local worker_plot = bpos_list [ bpos.worker . lives_at ] ;
formspec = formspec .. ' -, ' ..
( worker_plot.beds [ 1 ] . title or ' - ' ) .. ' , ' ..
( worker_plot.beds [ 1 ] . first_name or ' - ' ) .. ' , ' ..
" lives in the " .. tostring ( btype2.typ ) .. " on plot " .. tostring ( bpos.worker . lives_at ) .. ' , ' ;
elseif ( bpos.belongs_to and bpos_list [ bpos.belongs_to ] ) then
formspec = formspec .. ' -,-,-, ' ;
local owner_plot = bpos_list [ bpos.belongs_to ] ;
if ( owner_plot and owner_plot.beds and owner_plot.beds [ 1 ] ) then
formspec = formspec .. " owned by " ..
( owner_plot.beds [ 1 ] . title or ' ? ' ) .. ' ' ..
( owner_plot.beds [ 1 ] . first_name or ' ? ' ) ..
minetest.formspec_escape ( " [plot " .. tostring ( bpos.belongs_to ) .. ' ] ' ) .. ' , ' ;
else
formspec = formspec .. " owned by " .. minetest.formspec_escape ( " [plot " .. tostring ( bpos.belongs_to ) .. ' ] ' ) .. ' , ' ;
end
elseif ( bpos.btype == " road " ) then
if ( not ( bpos.parent_road_plot ) ) then
formspec = formspec .. ' -,-,-,road stump, ' ;
elseif ( bpos.parent_road_plot == 0 ) then
formspec = formspec .. ' -,-,-,main road, ' ;
else
formspec = formspec .. ' -,-,-,road nr. ' .. tostring ( bpos.road_nr ) ..
minetest.formspec_escape ( ' , sideroad of ' ) ;
if ( bpos_list [ bpos.parent_road_plot ] . parent_road_plot == 0 ) then
formspec = formspec .. ' the main road, ' ;
else
formspec = formspec .. ' road nr. ' ..
tostring ( bpos_list [ bpos.parent_road_plot ] . road_nr ) .. ' , ' ;
end
end
else
formspec = formspec .. ' -,-,-,-, ' ;
end
else
formspec = formspec .. tostring ( # bpos.beds ) .. ' , ' ..
( bpos.beds [ 1 ] . title or ' - ' ) .. ' , ' ..
( bpos.beds [ 1 ] . first_name or ' - ' ) .. ' , ' ;
if ( bpos.beds [ 1 ] . works_at
and bpos.beds [ 1 ] . works_at ~= plot_nr
and bpos_list [ bpos.beds [ 1 ] . works_at ] ) then
local btype2 = mg_villages.BUILDINGS [ bpos_list [ bpos.beds [ 1 ] . works_at ] . btype ] ;
formspec = formspec .. " works at the " .. tostring ( btype2.typ ) .. " on plot " .. tostring ( bpos.beds [ 1 ] . works_at ) .. " , " ;
else
formspec = formspec .. " -, " ;
end
end
end
formspec = formspec .. ' ;1] ' ;
minetest.show_formspec ( pname , formname , formspec ) ;
end
-- list all villages withhin a certain range of the player's position:
-- village_nr, distance from player, name of village, population,
-- type (i.e. "medieval"), x, y, z, diameter, #buildings, village/single house
-- this function is only used for the chat command "/villages" currently
2014-08-04 22:18:20 +02:00
mg_villages.list_villages_formspec = function ( player , formname , fields )
if ( not ( player ) or fields.quit ) then
return
end
local pname = player : get_player_name ( ) ;
local ppos = player : getpos ( ) ;
local radius = 1000000 ;
-- without the special priv, players can only obtain informatoin about villages which are very close by
if ( not ( minetest.check_player_privs ( pname , { mg_villages = true } ) ) ) then
2014-10-16 03:25:53 +02:00
radius = mg_villages.VILLAGE_DETECT_RANGE ;
2014-08-04 22:18:20 +02:00
end
local formspec = ' size[12,12] ' ..
2017-07-24 19:07:34 +02:00
' button_exit[4.0,1.0;2,0.5;quit;Exit] ' ..
2014-08-04 22:18:20 +02:00
' tablecolumns[ ' ..
' text,align=right; ' .. -- village number
' text,align=right; ' .. -- distance from player
' text,align=center; ' .. -- name of village
2017-07-24 04:48:02 +02:00
' text,align=center; ' .. -- inhabitants
2014-08-04 22:18:20 +02:00
' text,align=center; ' .. -- typ of village
' text,align=right; ' .. -- x
' text,align=right; ' .. -- y
' text,align=right; ' .. -- z
' text,align=right; ' .. -- size
2017-07-24 04:48:02 +02:00
' text,align=center; ' .. -- #houses where inhabitants may live or work
2014-11-29 06:23:08 +01:00
' text,align=right] ' ..
2017-07-24 04:48:02 +02:00
' table[0.1,2.0;11.4,8.8; ' .. formname .. ' ; ' ..
' Nr,Dist,Name of village,Population,Type of village,_X_,_H_,_Z_,Size, ' .. minetest.formspec_escape ( ' #Buildings ' ) .. ' ,, ' ;
2014-08-04 22:18:20 +02:00
2017-07-24 18:21:32 +02:00
mg_villages.tmp_player_village_list [ pname ] = { } ;
2014-08-04 22:18:20 +02:00
for k , v in pairs ( mg_villages.all_villages ) do
local dx = math.abs ( v.vx - ppos.x ) ;
local dz = math.abs ( v.vz - ppos.z ) ;
-- distance in y direction is less relevant here and may be ignored
if ( dx + dz < radius ) then
local dist = math.sqrt ( dx * dx + dz * dz ) ;
2014-11-29 06:23:08 +01:00
local is_full_village = ' village ' ;
if ( v.is_single_house ) then
is_full_village = ' ' ;
end
2017-07-24 04:48:02 +02:00
-- count the inhabitants
if ( not ( v.population ) ) then
v.population = 0 ;
for _ , pos in ipairs ( v.to_add_data . bpos ) do
if ( pos and pos.beds ) then
v.population = v.population + # pos.beds ;
end
end
end
local show_population = v.population ;
if ( show_population == 0 ) then
show_population = " - " ;
end
2014-08-04 22:18:20 +02:00
formspec = formspec ..
v.nr .. ' , ' ..
tostring ( math.floor ( dist ) ) .. ' , ' ..
2014-11-29 06:23:08 +01:00
tostring ( v.name or ' unknown ' ) .. ' , ' ..
2017-07-24 04:48:02 +02:00
show_population .. ' , ' ..
2014-08-04 22:18:20 +02:00
v.village_type .. ' , ' ..
tostring ( v.vx ) .. ' , ' ..
tostring ( v.vh ) .. ' , ' ..
tostring ( v.vz ) .. ' , ' ..
2014-11-29 06:23:08 +01:00
tostring ( v.vs ) .. ' , ' ..
tostring ( v.anz_buildings ) .. ' , ' ..
tostring ( is_full_village ) .. ' , ' ;
2017-07-24 18:21:32 +02:00
-- store which list we have shown to this particular player
table.insert ( mg_villages.tmp_player_village_list [ pname ] , k ) ;
2014-08-04 22:18:20 +02:00
end
end
2017-07-24 04:48:02 +02:00
formspec = formspec .. ' ;1] ' ;
-- 'tabheader[0.1,2.6;spalte;Nr,Dist,Name of village,Population,Type of village,_X_,_H_,_Z_,Size,'..minetest.formspec_escape('#Buildings')..';;true;true]';
2014-08-04 22:18:20 +02:00
minetest.show_formspec ( pname , formname , formspec ) ;
end
minetest.register_chatcommand ( ' villages ' , {
description = " Shows a list of all known villages. " ,
privs = { } ,
func = function ( name , param )
2017-07-26 04:30:32 +02:00
mg_villages.list_villages_formspec ( minetest.get_player_by_name ( name ) , " mg_villages:formspec_list_villages " , { } ) ;
2014-08-04 22:18:20 +02:00
end
} ) ;
minetest.register_chatcommand ( ' visit ' , {
description = " Teleports you to a known village. " ,
params = " <village number> " ,
privs = { } ,
func = function ( name , param )
2014-10-16 03:25:53 +02:00
if ( mg_villages.REQUIRE_PRIV_FOR_TELEPORT and not ( minetest.check_player_privs ( name , { mg_villages = true } ) ) ) then
2014-08-04 22:18:20 +02:00
minetest.chat_send_player ( name , " You need the 'mg_villages' priv in order to teleport to villages using this command. " ) ;
return ;
end
if ( not ( param ) or param == " " ) then
minetest.chat_send_player ( name , " Which village do you want to visit? Please provide the village number! " ) ;
return ;
end
local nr = tonumber ( param ) ;
for id , v in pairs ( mg_villages.all_villages ) do
-- we have found the village
if ( v and v.nr == nr ) then
2014-09-20 17:53:20 +02:00
minetest.chat_send_player ( name , " Initiating transfer to village no. " .. tostring ( v.nr ) .. " , called " .. ( tostring ( v.name or ' unknown ' ) ) .. " . " ) ;
2014-08-04 22:18:20 +02:00
local player = minetest.get_player_by_name ( name ) ;
player : moveto ( { x = v.vx , y = ( v.vh + 1 ) , z = v.vz } , false ) ;
return ;
end
end
-- no village found
minetest.chat_send_player ( name , " There is no village with the number " .. tostring ( param ) .. " (yet?). " ) ;
end
} ) ;
2017-07-28 16:41:52 +02:00
minetest.register_chatcommand ( ' village_mob_repopulate ' , {
description = " Discards old mob data and assigns beds and workplaces anew. Mobs get new names. " ,
params = " <village number> " ,
privs = { } ,
func = function ( name , param )
if ( not ( minetest.check_player_privs ( name , { protection_bypass = true } ) ) ) then
minetest.chat_send_player ( name , " You need the 'protection_bypass' priv in order to delete all the old mob data of a village and to recalculate it anew. " ) ;
return ;
end
if ( not ( param ) or param == " " ) then
minetest.chat_send_player ( name , " Which village do you want to repopulate? Please provide the village number! " ) ;
return ;
end
local nr = tonumber ( param ) ;
for id , v in pairs ( mg_villages.all_villages ) do
-- we have found the village
if ( v and v.nr == nr ) then
minetest.chat_send_player ( name , " Deleting information about workplaces and beds. Recalculating. Assigning new data for village no. " .. tostring ( v.nr ) .. " , called " .. ( tostring ( v.name or ' unknown ' ) ) .. " . " ) ;
-- move the player to the center of the village he just changed
local player = minetest.get_player_by_name ( name ) ;
player : moveto ( { x = v.vx , y = ( v.vh + 1 ) , z = v.vz } , false ) ;
local village_id = tostring ( v.vx ) .. ' : ' .. tostring ( v.vz ) ;
-- actually do the reassigning
mg_villages.inhabitants . assign_mobs ( v , village_id , true ) ;
-- save the modified data
save_restore.save_data ( ' mg_all_villages.data ' , mg_villages.all_villages ) ;
return ;
end
end
-- no village found
minetest.chat_send_player ( name , " There is no village with the number " .. tostring ( param ) .. " (yet?). " ) ;
end
} ) ;