forked from Sokomine/mg_villages
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chat_commands.lua
281 lines (246 loc) · 10.9 KB
/
chat_commands.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
-- Intllib
local S = mg_villages.intllib
minetest.register_privilege("mg_villages", { description = S("Allows to teleport to villages via").." /vist <nr>", give_to_singleplayer = false});
-- 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..)
mg_villages.get_road_list( fields.village_id, false );
-- 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
local formspec = 'size[12,12]'..
'field[20,20;0.1,0.1;village_id;VillageID;'..minetest.formspec_escape( fields.village_id ).."]"..
'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]'..
prev_next_button..
'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
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
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
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:get_pos();
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
radius = mg_villages.VILLAGE_DETECT_RANGE;
end
local formspec = 'size[12,12]'..
'button_exit[4.0,1.0;2,0.5;quit;Exit]'..
'tablecolumns[' ..
'text,align=right;'.. -- village number
'text,align=right;'.. -- distance from player
'text,align=center;'.. -- name of village
'text,align=center;'.. -- inhabitants
'text,align=center;'.. -- typ of village
'text,align=right;'.. -- x
'text,align=right;'.. -- y
'text,align=right;'.. -- z
'text,align=right;'.. -- size
'text,align=center;'.. -- #houses where inhabitants may live or work
'text,align=right]'..
'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')..',,';
mg_villages.tmp_player_village_list[ pname ] = {};
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 );
local is_full_village = 'village';
if( v.is_single_house ) then
is_full_village = '';
end
-- 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
formspec = formspec..
v.nr..','..
tostring( math.floor( dist ))..','..
tostring( v.name or 'unknown' )..','..
show_population..','..
v.village_type..','..
tostring( v.vx )..','..
tostring( v.vh )..','..
tostring( v.vz )..','..
tostring( v.vs )..','..
tostring( v.anz_buildings )..','..
tostring( is_full_village )..',';
-- store which list we have shown to this particular player
table.insert( mg_villages.tmp_player_village_list[ pname ], k );
end
end
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]';
minetest.show_formspec( pname, formname, formspec );
end
minetest.register_chatcommand( 'villages', {
description = S("Shows a list of all known villages."),
privs = {},
func = function(name, param)
mg_villages.list_villages_formspec( minetest.get_player_by_name( name ), "mg_villages:formspec_list_villages", {});
end
});
minetest.register_chatcommand( 'visit', {
description = S("Teleports you to a known village."),
params = "<village number>",
privs = {},
func = function(name, param)
if( mg_villages.REQUIRE_PRIV_FOR_TELEPORT and not( minetest.check_player_privs( name, {mg_villages=true}))) then
minetest.chat_send_player( name, S("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, S("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
minetest.chat_send_player( name, S("Initiating transfer to village no. @1, called @2.", tostring( v.nr ), tostring( v.name or 'unknown')));
local player = minetest.get_player_by_name( name );
player:move_to( { 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
});
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:move_to( { 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 );
-- adjust beds and workplaces
mg_villages.inhabitants.prepare_metadata( v, village_id, nil, nil );
return;
end
end
-- no village found
minetest.chat_send_player( name, S("There is no village with the number @1 (Yet?)."), tostring( param ));
end
});