-
Notifications
You must be signed in to change notification settings - Fork 2
/
init.lua
332 lines (267 loc) · 10.4 KB
/
init.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
-- aviator, place block and fly, now also TNT resistant
aviation = {}
aviator_hud_id = {}
local getsetting = tonumber((minetest.settings:get("active_block_range")) or 1) * 32
local flength = tonumber((minetest.settings:get("aviator_flight_length")) or 30) * 60 -- how many seconds you can fly
local checktime = 1 -- check interval
local maxdistance = tonumber((minetest.settings:get("aviator_flight_radius")) or 50) -- maxradius
local timer = 0
local trans = true -- no permanent forceload block if server shuts down
local force = false
if minetest.get_modpath("mesecons_mvps") then -- pull and push resistant to pistons
mesecon.register_mvps_stopper("aviator:aviator")
end
if maxdistance > getsetting then force = true end
local function aviator_get_air_pos(pos)
local nodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, {"air"})
if not nodes or #nodes < 1 then
return nil
else
return nodes[math.random(#nodes)]
end
end
local function aviator_update_hud(player,name,leftover,distance) -- hud_change(id, stat, value) `position`, `name`, `scale`, `text`, `number`, `item`, `dir`
if distance > maxdistance and distance < (maxdistance+10) then
player:hud_change(aviator_hud_id[name], 'text', ">>> Warning, you left fly area <<<")
player:hud_change(aviator_hud_id[name], 'position' , {x=0.5, y=0.80})
player:hud_change(aviator_hud_id[name], 'number', 0xFF0000)
leftover = -1
end
if leftover > 10 then
if distance < (maxdistance-10) then
player:hud_change(aviator_hud_id[name], 'text', ">>> "..math.floor(leftover/60).." minutes left, Distance: "..distance.." <<<")
player:hud_change(aviator_hud_id[name], 'position' , {x=0.5, y=0.80})
player:hud_change(aviator_hud_id[name], 'number', 0xFFFF00)
end
if distance >= (maxdistance-10) and distance <= maxdistance then
player:hud_change(aviator_hud_id[name], 'text', ">>> "..math.floor(leftover/60).." minutes left, Distance: "..distance.. " <<< !NEAR MAXRADIUS!")
player:hud_change(aviator_hud_id[name], 'position' , {x=0.5, y=0.80})
player:hud_change(aviator_hud_id[name], 'number', 0xFFA500)
end
end
if leftover <= 10 and leftover >0 then
player:hud_change(aviator_hud_id[name], 'text', ">>> "..leftover.." <<<")
player:hud_change(aviator_hud_id[name], 'position' , {x=0.5, y=0.45})
player:hud_change(aviator_hud_id[name], 'number', 0xFF0000)
end
return leftover
end
local function aviator_remove(pos, player, leave)
local name = player:get_player_name()
if aviation[name] ~= nil then
local items = ItemStack("aviator:aviator 1")
local meta = minetest.deserialize(items:get_metadata()) or {}
local ntime = minetest.get_node_timer(aviation[name])
local timeout = ntime:get_timeout()
local elapsed = ntime:get_elapsed()
local inv = minetest.get_inventory({type="player", name=name})
local privs = minetest.get_player_privs(name)
meta.runtime = -1
items:set_metadata(minetest.serialize(meta))
if not inv:room_for_item("main", items) and not leave then
minetest.chat_send_player(name, core.colorize('#ff0000', ">>> ERROR: could not take aviator, inventory full !"))
player:set_pos(aviation[name])
return
end
if vector.distance(pos, aviation[name]) == 0 then
meta.runtime = timeout - elapsed
items:set_metadata(minetest.serialize(meta))
if inv:room_for_item("main", items) then
inv:add_item("main", items)
else
local dpos = player:get_pos()
minetest.spawn_item(dpos, items)
end
ntime:stop()
if aviator_hud_id[name] then
player:hud_remove(aviator_hud_id[name])
end
privs.fly = nil
minetest.set_player_privs(name, privs)
minetest.set_node(aviation[name], {name = "air"})
aviation[name] = nil
if force then core.forceload_free_block(pos,trans) end
end
end
return
end
if minetest.get_modpath("technic") and minetest.get_modpath("moreores") then
minetest.register_craft({
output = 'aviator:aviator',
recipe = {
{"moreores:mithril_ingot", 'default:diamond', "moreores:mithril_ingot"},
{'default:diamond', "technic:uranium35_ingot", 'default:diamond'},
{"moreores:mithril_ingot", 'default:diamond', "moreores:mithril_ingot"},
}
})
elseif minetest.get_modpath("basic_machines") then
-- do it with constructor !
basic_machines.craft_recipes["aviator"] = {item = "aviator:aviator", description = "let you fly "..math.floor(flength/60).."min in an area of "..maxdistance.." nodes", craft = {"default:diamondblock 16","basic_machines:power_rod 25", "default:mese 16","basic_machines:keypad"}, tex = "aviator_aviator_side"}
table.insert(basic_machines.craft_recipe_order,"aviator")
basic_machines.hardness["aviator:aviator"] = 999999
else
minetest.register_craft({
output = 'aviator:aviator',
recipe = {
{"default:gold_ingot", 'default:diamond', "default:gold_ingot"},
{'default:diamond', "default:diamondblock", 'default:diamond'},
{"default:gold_ingot", 'default:diamond', "default:gold_ingot"},
}
})
end
minetest.register_node("aviator:aviator", {
description = "aviation device, fly priv for "..(flength/60).." min",
tiles = {"aviator_aviator_top.png",
"aviator_aviator_bottom.png",
"aviator_aviator_side.png",
"aviator_aviator_side.png",
"aviator_aviator_side.png",
"aviator_aviator_side.png"},
is_ground_content = false,
diggable = true,
groups = {oddly_breakable_by_hand=3},
liquids_pointable = true,
light_source = 12,
node_placement_prediction = "", -- important to avoid double placement
on_blast = function() end, -- TNT resistant
on_place = function(itemstack, placer, pointed_thing)
local name = placer:get_player_name()
local meta = minetest.deserialize(itemstack:get_metadata()) or {}
local pos = aviator_get_air_pos(pointed_thing.under)
if not pos then return itemstack end
if not aviation[name] then
local nname = itemstack:get_name()
local timer = minetest.get_node_timer(pos)
local leftover = 0
minetest.set_node(pos, {name=nname})
itemstack:take_item()
aviation[name]=pos
if force then
if core.forceload_block(pos,trans) == false then
-- minetest.chat_send_all("Forceload Error")
end
end
if not meta.runtime then
timer:start(flength)
leftover = flength
else
leftover = meta.runtime
timer:start(meta.runtime)
meta = {}
itemstack:set_metadata(minetest.serialize(meta))
end
aviator_hud_id[name] = placer:hud_add({
hud_elem_type = "text";
position = {x=0.5, y=0.80};
text = ">>> "..math.floor(leftover/60).." minutes left <<<";number = 0xFFFF00;})
else
minetest.chat_send_player(name,core.colorize('#eeee00', "You placed already one Aviator at: "..aviation[name].x..","..aviation[name].y..","..aviation[name].z))
end
return itemstack
end,
on_dig = function(pos, node, player)
aviator_remove(pos, player)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local name = digger:get_player_name()
local ctime = minetest.get_node_timer(pos)
if aviation[name] ~= nil or ctime:is_started() then
local inv = minetest.get_inventory({type="player", name=name})
local items = ItemStack("aviator:aviator 1")
inv:remove_item("main", items)
minetest.set_node(pos,oldnode)
end
end
})
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= checktime then
local players = minetest.get_connected_players();
for _,player in pairs(players) do
local name = player:get_player_name()
if aviation[name] ~= nil and aviation[name] ~= {} then
local pos = player:get_pos()
local ntime = minetest.get_node_timer(aviation[name])
local timeout = ntime:get_timeout()
local elapsed = ntime:get_elapsed()
local leftover = timeout - elapsed
local distance = math.floor(vector.distance(pos, aviation[name]))
local privs = minetest.get_player_privs(name)
if timeout > 0 then
if distance <= maxdistance then
privs.fly = true
minetest.set_player_privs(name, privs)
leftover = aviator_update_hud(player,name,leftover,distance)
else
if distance > (maxdistance+10) then
player:hud_remove(aviator_hud_id[name])
aviator_remove(aviation[name], player)
leftover = -1
end
privs.fly = nil
minetest.set_player_privs(name, privs)
end
leftover = aviator_update_hud(player,name,leftover,distance)
else
if aviator_hud_id[name] then
player:hud_remove(aviator_hud_id[name])
end
privs.fly = nil
minetest.set_player_privs(name, privs)
minetest.set_node(aviation[name], {name = "air"})
aviation[name] = nil
end
end
end
timer = 0
end
end)
-- add aviator to inventory if any
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if aviation[name] ~= nil then
local privs = minetest.get_player_privs(name)
privs.fly = nil
minetest.set_player_privs(name, privs)
aviator_remove(aviation[name], player, true)
aviation[name] = nil
end
end)
-- still someone with fly priv ? strange.
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
local privs = minetest.get_player_privs(name)
if privs.fly and not privs.server then
privs.fly = nil
minetest.set_player_privs(name, privs)
end
end)
-- add aviator to inventory if any
minetest.register_on_shutdown(function()
local players = minetest.get_connected_players()
for _,player in pairs(players) do
local name = player:get_player_name()
if aviation[name] ~= nil then
local privs = minetest.get_player_privs(name)
privs.fly = nil
minetest.set_player_privs(name, privs)
aviator_remove(aviation[name], player, true)
aviation[name] = nil
end
end
end)
-- add chatcommand to call back aviator
minetest.register_chatcommand("7", {
params = "",
description = "Calls your aviator back to inventory",
privs = {interact = true},
func = function(name, param)
local player = minetest.get_player_by_name(name)
if aviation[name] ~= nil then
aviator_remove(aviation[name], player)
else
local colorstring = core.colorize('#ff0000', " >>> you did not place an aviator ")
minetest.chat_send_player(name,colorstring)
end
end
})