Browse code

update walking_light from petermaloney fork

* https://github.com/petermaloney/walking_light
* because this fork has an addLightItem function
* I'm hoping the lack of 3d_armor doesn't break everything

Phil Morrell authored on 2018-09-06 06:49:23
Showing 10 changed files
... ...
@@ -1,125 +1,528 @@
1
+-- list of all players seen by minetest.register_on_joinplayer
1 2
 local players = {}
3
+-- all player positions last time light was updated: {player_name : {x, y, z}}
2 4
 local player_positions = {}
5
+-- all light positions of light that currently is created {player_name : {i: {x, y, z}}
6
+local light_positions = {}
7
+-- last item seen wielded by players
3 8
 local last_wielded = {}
4 9
 
10
+-- toggles debug mode
11
+local walking_light_debug = false
12
+-- name of light node, changed by toggling debug mode
13
+local walking_light_node = nil
14
+
15
+-- initialize walking light
16
+walking_light = {}
17
+
18
+-- list of items that use walking light
19
+local light_items = {
20
+	"default:torch", "walking_light:pick_mese",
21
+	"walking_light:helmet_diamond", "walking_light:megatorch"
22
+}
23
+
24
+function walking_light.addLightItem(item)
25
+	for I in pairs(light_items) do
26
+		if item == light_items[I] then
27
+			minetest.log("warning", "[walking_light] \"" .. item .. "\" is already light item.")
28
+			return
29
+		end
30
+	end
31
+	
32
+	table.insert(light_items, -1, item)
33
+end
34
+
35
+function walking_light.getLightItems()
36
+	return light_items
37
+end
38
+
39
+
40
+-- from http://lua-users.org/wiki/IteratorsTutorial
41
+-- useful for removing things from a table because removing from the middle makes it skip elements otherwise
42
+function ripairs(t)
43
+  local function ripairs_it(t,i)
44
+    i=i-1
45
+    local v=t[i]
46
+    if v==nil then return v end
47
+    return i,v
48
+  end
49
+  return ripairs_it, t, #t+1
50
+end
51
+
52
+-- formats a vector with shorter output than dump
53
+local function dumppos(pos)
54
+	if pos == nil then
55
+		return "nil"
56
+	end
57
+	local x = "nil"
58
+	if pos.x then
59
+		x = pos.x
60
+	end
61
+	local y = "nil"
62
+	if pos.y then
63
+		y = pos.y
64
+	end
65
+	local z = "nil"
66
+	if pos.z then
67
+		z = pos.z
68
+	end
69
+
70
+	return "(" .. x .. "," .. y .. "," .. z .. ")"
71
+end
72
+
73
+-- formats a table containing vectors with shorter output than dump
74
+local function dumppostable(t)
75
+	if t == nil then
76
+		return "nil"
77
+	end
78
+	if #t == 0 then
79
+		return "0{}"
80
+	end
81
+
82
+	ret = #t .. "{\n"
83
+	for i,pos in ipairs(t) do
84
+		ret = ret .. "    " .. dumppos(pos) .. "\n"
85
+	end
86
+	ret = ret .. "}"
87
+	return ret
88
+end
89
+
90
+function mt_get_node_or_nil(pos)
91
+	if pos == nil then
92
+		print("ERROR: walking_light.mt_get_node_or_nil(), pos is nil")
93
+		print(debug.traceback("Current Callstack:\n"))
94
+		return nil
95
+	end
96
+	return minetest.get_node_or_nil(pos)
97
+end
98
+
99
+function mt_add_node(pos, sometable)
100
+	if pos == nil then
101
+		print("ERROR: walking_light.mt_add_node(), pos is nil")
102
+		print(debug.traceback("Current Callstack:\n"))
103
+		return nil
104
+	end
105
+	if sometable == nil then
106
+		print("ERROR: walking_light.mt_add_node(), sometable is nil")
107
+		print(debug.traceback("Current Callstack:\n"))
108
+		return nil
109
+	end
110
+	minetest.add_node(pos,sometable)
111
+end
112
+
5 113
 function round(num) 
6 114
 	return math.floor(num + 0.5) 
7 115
 end
8 116
 
117
+local function poseq(pos1, pos2)
118
+	if pos1 == nil and pos2 == nil then
119
+		return true
120
+	end
121
+	if pos1 == nil or pos2 == nil then
122
+		return false
123
+	end
124
+	return pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z
125
+end
126
+
127
+-- return true if the player moved since last player_positions update
128
+local function player_moved(player)
129
+	local player_name = player:get_player_name()
130
+	local pos = player:getpos()
131
+	local rounded_pos = vector.round(pos)
132
+	local oldpos = player_positions[player_name]
133
+	if oldpos == nil or not poseq(rounded_pos, oldpos) then
134
+		-- if oldpos is nil, we assume they just logged in, so consider them moved
135
+--		print("DEBUG: walking_light, player_moved(); moved = true; rounded_pos = " .. dumppos(rounded_pos) .. ", oldpos = " .. dumppos(oldpos))
136
+		return true
137
+	end
138
+--	print("DEBUG: walking_light, player_moved(); moved = false; rounded_pos = " .. dumppos(rounded_pos) .. ", oldpos = " .. dumppos(oldpos))
139
+	return false
140
+end
141
+
142
+-- same as table.remove(t,remove_pos), but uses poseq instead of comparing references (does lua have comparator support, so this isn't needed?)
143
+local function table_remove_pos(t, remove_pos)
144
+--	local DEBUG_oldsize = #t
145
+
146
+	for i,pos in ipairs(t) do
147
+		if poseq(pos, remove_pos) then
148
+			table.remove(t, i)
149
+			break
150
+		end
151
+	end
152
+
153
+--	local DEBUG_newsize = #t
154
+--	print("DEBUG: walking_light.table_remove_pos(), oldsize = " .. DEBUG_oldsize .. ", newsize = " .. DEBUG_newsize)
155
+end
156
+
157
+-- same as t[remove_pos], but uses poseq instead of comparing references (does lua have comparator support, so this isn't needed?)
158
+local function table_contains_pos(t, remove_pos)
159
+	for i,pos in ipairs(t) do
160
+		if poseq(pos, remove_pos) then
161
+			return true
162
+		end
163
+	end
164
+	return false
165
+end
166
+
167
+-- same as table.insert(t,pos) but makes sure it is not duplicated
168
+local function table_insert_pos(t, pos)
169
+	if not table_contains_pos( pos ) then
170
+		table.insert(t, pos)
171
+	end
172
+end
173
+
174
+local function is_light(node)
175
+	if node ~= nil and ( node.name == "walking_light:light" or node.name == "walking_light:light_debug" ) then
176
+		return true
177
+	end
178
+	return false
179
+end
180
+    
181
+-- removes light at the given position
182
+-- player is optional
183
+local function remove_light(player, pos)
184
+	local player_name
185
+	if player then
186
+		player_name = player:get_player_name()
187
+	end
188
+	local node = mt_get_node_or_nil(pos)
189
+	if is_light(node) then
190
+		mt_add_node(pos,{type="node",name="air"})
191
+		if player_name then
192
+			table_remove_pos(light_positions[player_name], pos)
193
+		end
194
+	else
195
+		if node ~= nil then
196
+			print("WARNING: walking_light.remove_light(), pos = " .. dumppos(pos) .. ", tried to remove light but node was " .. node.name)
197
+			table_remove_pos(light_positions[player_name], pos)
198
+		else
199
+			print("WARNING: walking_light.remove_light(), pos = " .. dumppos(pos) .. ", tried to remove light but node was nil")
200
+		end
201
+	end
202
+end
203
+
204
+-- removes all light owned by a player
205
+local function remove_light_player(player)
206
+	local player_name = player:get_player_name()
207
+
208
+    for i,old_pos in ripairs(light_positions[player_name]) do
209
+		if old_pos then
210
+--			print("DEBUG: walking_light.remove_light_player(), removing old light; old_pos = " .. dumppos(old_pos))
211
+			remove_light(player, old_pos)
212
+		end
213
+	end
214
+--	print("DEBUG: walking_light.remove_light_player(), done; light_positions = " .. dumppostable(light_positions[player_name]))
215
+end
216
+
217
+local function can_add_light(pos)
218
+	local node  = mt_get_node_or_nil(pos)
219
+	if node == nil or node.name == "air" then
220
+--		print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", true")
221
+		return true
222
+	elseif is_light(node) then
223
+--		print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", true")
224
+		return true
225
+	end
226
+--	print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", false")
227
+	return false
228
+end
229
+
230
+-- old function returns pos instead of table, for only one position
231
+local function pick_light_position_regular(player, pos)
232
+	if can_add_light(pos) then
233
+		return {pos}
234
+	end
235
+
236
+	local pos2
237
+
238
+	-- if pos is not possible, try the old player position first, to make it more likely that it has a line of sight
239
+	local player_name = player:get_player_name()
240
+	local oldplayerpos = player_positions[player_name]
241
+	if oldplayerpos and can_add_light( vector.new(oldplayerpos.x, oldplayerpos.y + 1, oldplayerpos.z) ) then
242
+		return oldplayerpos 
243
+	end
244
+
245
+	-- if not, try all positions around the pos
246
+	pos2 = vector.new(pos.x + 1, pos.y, pos.z)
247
+	if can_add_light( pos2 ) then
248
+		return {pos2}
249
+	end
250
+
251
+	pos2 = vector.new(pos.x - 1, pos.y, pos.z)
252
+	if can_add_light( pos2 ) then
253
+		return {pos2}
254
+	end
255
+
256
+	pos2 = vector.new(pos.x, pos.y, pos.z + 1)
257
+	if can_add_light( pos2 ) then
258
+		return {pos2}
259
+	end
260
+
261
+	pos2 = vector.new(pos.x, pos.y, pos.z - 1)
262
+	if can_add_light( pos2 ) then
263
+		return {pos2}
264
+	end
265
+
266
+	pos2 = vector.new(pos.x, pos.y + 1, pos.z)
267
+	if can_add_light( pos2 ) then
268
+		return {pos2}
269
+	end
270
+
271
+	pos2 = vector.new(pos.x, pos.y - 1, pos.z)
272
+	if can_add_light( pos2 ) then
273
+		return {pos2}
274
+	end
275
+
276
+	return nil
277
+end
278
+
279
+-- new function, returns table
280
+local function pick_light_position_radius(player, pos, ret, radius)
281
+	local pos2
282
+	local step = 4
283
+	local unstep = 1/step
284
+
285
+	for x = pos.x - radius, pos.x + radius, step do
286
+		for y = pos.y - radius, pos.y + radius, step do
287
+			for z = pos.z - radius, pos.z + radius, step do
288
+				pos2 = vector.new(round(x*unstep)*step, round(y*unstep)*step, round(z*unstep)*step)
289
+				distance = math.sqrt(math.pow(pos.x - x, 2) + math.pow(pos.y - y, 2) + math.pow(pos.z - z, 2))
290
+				if distance <= radius and can_add_light( pos2 ) then
291
+					table.insert(ret, pos2)
292
+				end
293
+			end
294
+		end
295
+	end
296
+
297
+	return ret
298
+end
299
+
300
+local function pick_light_position_mega(player, pos)
301
+	local ret = {}
302
+
303
+	if can_add_light(pos) then
304
+		table.insert(ret, pos)
305
+	end
306
+	pick_light_position_radius(player, pos, ret, 10)
307
+
308
+	return ret
309
+end
310
+
311
+local function pick_light_position(player, pos, light_item)
312
+	if light_item == "walking_light:megatorch" then
313
+		return pick_light_position_mega(player, pos)
314
+	end
315
+	return pick_light_position_regular(player, pos)
316
+end
317
+
318
+-- adds light at the given position
319
+local function add_light(player, pos)
320
+	local player_name = player:get_player_name()
321
+	local node  = mt_get_node_or_nil(pos)
322
+	if node == nil then
323
+		-- don't do anything for nil blocks... they are non-loaded blocks, so we don't want to overwrite anything there
324
+--		print("DEBUG: walking_light.add_light(), node is nil, pos = " .. dumppos(pos))
325
+		return false
326
+	elseif node.name == "air" then
327
+		-- when the node that is already there is air, add light
328
+		mt_add_node(pos,{type="node",name=walking_light_node})
329
+		if not table_contains_pos(light_positions[player_name], pos) then
330
+			table_insert_pos(light_positions[player_name], pos)
331
+		end
332
+
333
+--		if node then
334
+--			print("DEBUG: add_light(), node.name = " .. node.name .. ", pos = " .. dumppos(pos))
335
+--		else
336
+--			print("DEBUG: add_light(), node.name = nil, pos = " .. dumppos(pos))
337
+--		end
338
+		return true
339
+	elseif is_light(node) then
340
+		-- no point in adding light where it is already, but we should assign it to the player so it gets removed (in case it has no player)
341
+--		print("DEBUG: add_light(), not adding; node.name = " .. node.name .. ", pos = " .. dumppos(pos))
342
+
343
+		if not table_contains_pos(light_positions[player_name], pos) then
344
+			table_insert_pos(light_positions[player_name], pos)
345
+		end
346
+
347
+		return true
348
+	end
349
+--	print("DEBUG: add_light(), not adding; node.name = " .. node.name)
350
+	return false
351
+end
352
+
353
+-- updates all the light around the player, depending on what they are wielding
354
+local function update_light_player(player)
355
+	-- if there is no player, there can be no update
356
+	if not player then
357
+		return
358
+	end
359
+
360
+	-- figure out if they wield light; this will be nil if not
361
+	local wielded_item = get_wielded_light_item(player)
362
+
363
+	local player_name = player:get_player_name()
364
+	local pos = player:getpos()
365
+	local rounded_pos = vector.round(pos)
366
+
367
+	-- check for a nil node where the player is; if it is nil, we assume the block is not loaded, so we return without updating player_positions
368
+	-- that way, it should add light next step
369
+	local node  = mt_get_node_or_nil(rounded_pos)
370
+	if node == nil then
371
+		return
372
+	end
373
+
374
+	if not player_moved(player) and wielded_item == last_wielded[player_name] then
375
+		-- no update needed if the wiedled light item is the same as before (including nil), and the player didn't move
376
+		return
377
+	end
378
+	last_wielded[player_name] = wielded_item;
379
+
380
+	local wantlightpos = nil
381
+	local wantpos = vector.new(rounded_pos.x, rounded_pos.y + 1, rounded_pos.z)
382
+	if wielded_item then
383
+		-- decide where light should be
384
+		wantlightpos = pick_light_position(player, wantpos, wielded_item)
385
+--		print("DEBUG: walking_light update_light_player(); wantpos = " .. dumppos(wantpos) .. ", wantlightpos = " .. dumppos(wantlightpos))
386
+	end
387
+
388
+	if wielded_item and wantlightpos then
389
+		-- add light that isn't already there
390
+		for i,newpos in ipairs(wantlightpos) do
391
+			add_light(player, newpos)
392
+		end
393
+	end
394
+
395
+	-- go through all light owned by the player to remove all but what should be kept
396
+    for i,oldlightpos in ripairs(light_positions[player_name]) do
397
+        if not wantlightpos or oldlightpos and oldlightpos.x and not table_contains_pos(wantlightpos, oldlightpos) then
398
+			remove_light(player, oldlightpos)
399
+        end
400
+    end
401
+
402
+	player_positions[player_name] = vector.round(pos)
403
+
404
+--	print("DEBUG: walking_light.update_light_player(): wantlightpos = " .. dumppostable(wantlightpos) .. ", light_positions = " .. dumppostable(light_positions[player_name]))
405
+end
406
+
407
+local function update_light_all()
408
+	-- go through all players to check
409
+	for i,player_name in ipairs(players) do
410
+		local player = minetest.get_player_by_name(player_name)
411
+		update_light_player(player)
412
+	end
413
+end
414
+
415
+-- return true if item is a light item
416
+function is_light_item(item)
417
+	for I in pairs(light_items) do
418
+		if item == light_items[I] then
419
+			return true
420
+		end
421
+	end
422
+	return false
423
+end
424
+
425
+-- returns a string, the name of the item found that is a light item
426
+function get_wielded_light_item(player)
427
+	local wielded_item = player:get_wielded_item():get_name()
428
+	if is_light_item(wielded_item) then
429
+		return wielded_item
430
+	end
431
+
432
+	-- check equipped armor - requires unified_inventory maybe
433
+	local player_name = player:get_player_name()
434
+	if player_name then
435
+		local armor_inv = minetest.get_inventory({type="detached", name=player_name.."_armor"})
436
+		if armor_inv then
437
+--            print( dump(armor_inv:get_lists()) )
438
+			local item_name = "walking_light:helmet_diamond"
439
+			local stack = ItemStack(item_name)
440
+			if armor_inv:contains_item("armor", stack) then
441
+				return item_name
442
+			end
443
+		end
444
+	end
445
+
446
+	return nil
447
+end
448
+
449
+-- return true if player is wielding a light item
450
+function wielded_light(player)
451
+	return get_wielded_light_item(player) ~= nil
452
+end
453
+
9 454
 minetest.register_on_joinplayer(function(player)
10 455
 	local player_name = player:get_player_name()
11 456
 	table.insert(players, player_name)
12
-	last_wielded[player_name] = player:get_wielded_item():get_name()
457
+	last_wielded[player_name] = get_wielded_light_item(player)
13 458
 	local pos = player:getpos()
14
-	local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
15
-	local wielded_item = player:get_wielded_item():get_name()
16
-	if wielded_item ~= "default:torch" and wielded_item ~= "walking_light:pick_mese" then
17
-		-- Neuberechnung des Lichts erzwingen
18
-		minetest.env:add_node(rounded_pos,{type="node",name="default:cobble"})
19
-		minetest.env:add_node(rounded_pos,{type="node",name="air"})
20
-	end
21
-	player_positions[player_name] = {}
22
-	player_positions[player_name]["x"] = rounded_pos.x;
23
-	player_positions[player_name]["y"] = rounded_pos.y;
24
-	player_positions[player_name]["z"] = rounded_pos.z;
459
+	player_positions[player_name] = nil
460
+	light_positions[player_name] = {}
461
+	update_light_player(player)
25 462
 end)
26 463
 
27 464
 minetest.register_on_leaveplayer(function(player)
28 465
 	local player_name = player:get_player_name()
29 466
 	for i,v in ipairs(players) do
30
-		if v == player_name then 
467
+		if v == player_name then
31 468
 			table.remove(players, i)
32
-			last_wielded[player_name] = nil
33
-			-- Neuberechnung des Lichts erzwingen
34
-			local pos = player:getpos()
35
-			local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
36
-			minetest.env:add_node(rounded_pos,{type="node",name="default:cobble"})
37
-			minetest.env:add_node(rounded_pos,{type="node",name="air"})
38
-			player_positions[player_name]["x"] = nil
39
-			player_positions[player_name]["y"] = nil
40
-			player_positions[player_name]["z"] = nil
41
-			player_positions[player_name]["m"] = nil
42
-			player_positions[player_name] = nil
43 469
 		end
44 470
 	end
471
+	last_wielded[player_name] = false
472
+	remove_light_player(player)
473
+	player_positions[player_name]=nil
45 474
 end)
46 475
 
47 476
 minetest.register_globalstep(function(dtime)
48 477
 	for i,player_name in ipairs(players) do
49
-		local player = minetest.env:get_player_by_name(player_name)
50
-		local wielded_item = player:get_wielded_item():get_name()
51
-		if wielded_item == "default:torch" or wielded_item == "walking_light:pick_mese" then
52
-			-- Fackel ist in der Hand
53
-			local pos = player:getpos()
54
-			local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
55
-			if (last_wielded[player_name] ~= "default:torch" and last_wielded[player_name] ~= "walking_light:pick_mese") or (player_positions[player_name]["x"] ~= rounded_pos.x or player_positions[player_name]["y"] ~= rounded_pos.y or player_positions[player_name]["z"] ~= rounded_pos.z) then
56
-				-- Fackel gerade in die Hand genommen oder zu neuem Node bewegt
57
-				local is_air  = minetest.env:get_node_or_nil(rounded_pos)
58
-				if is_air == nil or (is_air ~= nil and (is_air.name == "air" or is_air.name == "walking_light:light")) then
59
-					-- wenn an aktueller Position "air" ist, Fackellicht setzen
60
-					minetest.env:add_node(rounded_pos,{type="node",name="walking_light:light"})
61
-				end
62
-				if (player_positions[player_name]["x"] ~= rounded_pos.x or player_positions[player_name]["y"] ~= rounded_pos.y or player_positions[player_name]["z"] ~= rounded_pos.z) then
63
-					-- wenn Position ge�nder, dann altes Licht l�schen
64
-					local old_pos = {x=player_positions[player_name]["x"], y=player_positions[player_name]["y"], z=player_positions[player_name]["z"]}
65
-					-- Neuberechnung des Lichts erzwingen
66
-					local is_light = minetest.env:get_node_or_nil(old_pos)
67
-					if is_light ~= nil and is_light.name == "walking_light:light" then
68
-						minetest.env:add_node(old_pos,{type="node",name="default:cobble"})
69
-						minetest.env:add_node(old_pos,{type="node",name="air"})
70
-					end
71
-				end
72
-				-- gemerkte Position ist nun die gerundete neue Position
73
-				player_positions[player_name]["x"] = rounded_pos.x
74
-				player_positions[player_name]["y"] = rounded_pos.y
75
-				player_positions[player_name]["z"] = rounded_pos.z
76
-			end
77
-
78
-			last_wielded[player_name] = wielded_item;
79
-		elseif last_wielded[player_name] == "default:torch" or last_wielded[player_name] == "walking_light:pick_mese" then
80
-			-- Fackel nicht in der Hand, aber beim letzten Durchgang war die Fackel noch in der Hand
81
-			local pos = player:getpos()
82
-			local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
83
-			repeat
84
-				local is_light  = minetest.env:get_node_or_nil(rounded_pos)
85
-				if is_light ~= nil and is_light.name == "walking_light:light" then
86
-					-- minetest.env:remove_node(rounded_pos)
87
-					-- Erzwinge Neuberechnung des Lichts
88
-					minetest.env:add_node(rounded_pos,{type="node",name="default:cobble"})
89
-					minetest.env:add_node(rounded_pos,{type="node",name="air"})
90
-				end
91
-			until minetest.env:get_node_or_nil(rounded_pos) ~= "walking_light:light"
92
-			local old_pos = {x=player_positions[player_name]["x"], y=player_positions[player_name]["y"], z=player_positions[player_name]["z"]}
93
-			repeat
94
-				is_light  = minetest.env:get_node_or_nil(old_pos)
95
-				if is_light ~= nil and is_light.name == "walking_light:light" then
96
-					-- minetest.env:remove_node(old_pos)
97
-					-- Erzwinge Neuberechnung des Lichts
98
-					minetest.env:add_node(old_pos,{type="node",name="default:cobble"})
99
-					minetest.env:add_node(old_pos,{type="node",name="air"})
100
-				end
101
-			until minetest.env:get_node_or_nil(old_pos) ~= "walking_light:light"
102
-			last_wielded[player_name] = wielded_item
478
+		local player = minetest.get_player_by_name(player_name)
479
+		if player ~= nil then
480
+			update_light_player(player)
481
+		else
482
+			table.remove(players, i)
103 483
 		end
104 484
 	end
105 485
 end)
106 486
 
487
+minetest.register_node("walking_light:light_debug", {
488
+	drawtype = "glasslike",
489
+	tiles = {"walking_light_debug.png"},
490
+	inventory_image = minetest.inventorycube("walking_light.png"),
491
+	paramtype = "light",
492
+	walkable = false,
493
+	is_ground_content = true,
494
+	sunlight_propagates = true,
495
+	light_source = 14,
496
+	selection_box = {
497
+		type = "fixed",
498
+		fixed = {0, 0, 0, 0, 0, 0},
499
+	},
500
+})
501
+
107 502
 minetest.register_node("walking_light:light", {
108 503
 	drawtype = "glasslike",
109
-	tile_images = {"walking_light.png"},
110
-	-- tile_images = {"walking_light_debug.png"},
504
+	tiles = {"walking_light.png"},
111 505
 	inventory_image = minetest.inventorycube("walking_light.png"),
112 506
 	paramtype = "light",
113 507
 	walkable = false,
114 508
 	is_ground_content = true,
115
-	light_propagates = true,
116 509
 	sunlight_propagates = true,
117 510
 	light_source = 14,
118 511
 	selection_box = {
119
-        type = "fixed",
120
-        fixed = {0, 0, 0, 0, 0, 0},
121
-    },
512
+		type = "fixed",
513
+		fixed = {0, 0, 0, 0, 0, 0},
514
+	},
122 515
 })
516
+
517
+function update_walking_light_node()
518
+	if walking_light_debug then
519
+		walking_light_node = "walking_light:light_debug"
520
+	else
521
+		walking_light_node = "walking_light:light"
522
+	end
523
+end
524
+update_walking_light_node()
525
+
123 526
 minetest.register_tool("walking_light:pick_mese", {
124 527
 	description = "Mese Pickaxe with light",
125 528
 	inventory_image = "walking_light_mesepick.png",
... ...
@@ -135,6 +538,65 @@ minetest.register_tool("walking_light:pick_mese", {
135 538
 	},
136 539
 })
137 540
 
541
+minetest.register_tool("walking_light:helmet_diamond", {
542
+	description = "Diamond Helmet with light",
543
+	inventory_image = "walking_light_inv_helmet_diamond.png",
544
+	wield_image = "3d_armor_inv_helmet_diamond.png",
545
+	groups = {armor_head=15, armor_heal=12, armor_use=100},
546
+	wear = 0,
547
+})
548
+
549
+minetest.register_node("walking_light:megatorch", {
550
+    description = "Megatorch",
551
+    drawtype = "torchlike",
552
+    tiles = {
553
+        {
554
+            name = "default_torch_on_floor_animated.png",
555
+            animation = {
556
+                type = "vertical_frames",
557
+                aspect_w = 16,
558
+                aspect_h = 16,
559
+                length = 3.0
560
+            },
561
+        },
562
+        {
563
+            name="default_torch_on_ceiling_animated.png",
564
+            animation = {
565
+                type = "vertical_frames",
566
+                aspect_w = 16,
567
+                aspect_h = 16,
568
+                length = 3.0
569
+            },
570
+        },
571
+        {
572
+            name="default_torch_animated.png",
573
+            animation = {
574
+                type = "vertical_frames",
575
+                aspect_w = 16,
576
+                aspect_h = 16,
577
+                length = 3.0
578
+            },
579
+        },
580
+    },
581
+    inventory_image = "default_torch_on_floor.png",
582
+    wield_image = "default_torch_on_floor.png",
583
+    paramtype = "light",
584
+    paramtype2 = "wallmounted",
585
+    sunlight_propagates = true,
586
+    is_ground_content = false,
587
+    walkable = false,
588
+    light_source = 14,
589
+    selection_box = {
590
+        type = "wallmounted",
591
+        wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1},
592
+        wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
593
+        wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
594
+    },
595
+    groups = {choppy=2,dig_immediate=3,flammable=1,attached_node=1},
596
+    legacy_wallmounted = true,
597
+    --sounds = default.node_sound_defaults(),
598
+})
599
+
138 600
 minetest.register_craft({
139 601
 	output = 'walking_light:pick_mese',
140 602
 	recipe = {
... ...
@@ -142,3 +604,81 @@ minetest.register_craft({
142 604
 		{'default:pick_mese'},
143 605
 	}
144 606
 })
607
+
608
+minetest.register_craft({
609
+	output = 'walking_light:helmet_diamond',
610
+	recipe = {
611
+		{'default:torch'},
612
+		{'3d_armor:helmet_diamond'},
613
+	}
614
+})
615
+
616
+minetest.register_craft({
617
+	output = 'walking_light:megatorch',
618
+	recipe = {
619
+		{'default:torch', 'default:torch', 'default:torch'},
620
+		{'default:torch', 'default:torch', 'default:torch'},
621
+		{'default:torch', 'default:torch', 'default:torch'},
622
+	}
623
+})
624
+
625
+minetest.register_chatcommand("walking_light_clear_light", {
626
+	params = "<size>",
627
+	description = "Remove light nodes from the area",
628
+	func = function(name, param)
629
+		if not minetest.check_player_privs(name, {server=true}) then
630
+			return false, "You need the server privilege to use mapclearlight"
631
+		end
632
+
633
+		local pos = vector.round(minetest.get_player_by_name(name):getpos())
634
+		local size = tonumber(param) or 40
635
+
636
+		for i,v in ipairs({"walking_light:light", "walking_light:light_debug"}) do
637
+			point = minetest.find_node_near(pos, size/2, v)
638
+			while point do
639
+				remove_light(nil, point)
640
+				oldpoint = point
641
+				point = minetest.find_node_near(pos, size/2, v)
642
+				if poseq(oldpoint, point) then
643
+					return false, "Failed... infinite loop detected"
644
+				end
645
+			end
646
+		end
647
+		return true, "Done."
648
+	end,
649
+})
650
+
651
+minetest.register_chatcommand("walking_light_add_light", {
652
+	params = "<size>",
653
+	description = "Add walking_light:light to a position, without a player owning it",
654
+	func = function(name, param)
655
+		if not minetest.check_player_privs(name, {server=true}) then
656
+			return false, "You need the server privilege to use mapaddlight"
657
+		end
658
+
659
+		local pos = vector.round(minetest.get_player_by_name(name):getpos())
660
+		pos = vector.new(pos.x, pos.y + 1, pos.z)
661
+
662
+		if pos then
663
+			mt_add_node(pos,{type="node",name=walking_light_node})
664
+		end
665
+
666
+		return true, "Done."
667
+	end,
668
+})
669
+
670
+minetest.register_chatcommand("walking_light_debug", {
671
+	description = "Change to debug mode, so light blocks are visible.",
672
+	func = function(name, param)
673
+		if not minetest.check_player_privs(name, {server=true}) then
674
+			return false, "You need the server privilege to use walking_light_debug"
675
+		end
676
+
677
+		walking_light_debug = not walking_light_debug
678
+        update_walking_light_node()
679
+ 
680
+		return true, "Done."
681
+	end,
682
+})
683
+
684
+-- vim: ts=4 sw=4 softtabstop=4 smarttab noexpandtab
... ...
@@ -1,9 +1,12 @@
1
-117c117
1
+495c495
2 2
 < 	light_source = 13,
3 3
 ---
4 4
 > 	light_source = 14,
5
-144c144
6
-< })
7
-\ No newline at end of file
5
+510c510
6
+< 	light_source = 13,
7
+---
8
+> 	light_source = 14,
9
+588c588
10
+<     light_source = 13,
8 11
 ---
9
-> })
12
+>     light_source = 14,
10 13
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+minetest mod walking_light
2
+
3
+forked from 0.6 https://forum.minetest.net/viewtopic.php?f=11&t=2621&hilit=walking+light
4
+
5
+Licensing:
6
+==========
7
+
8
+If not noted elsewhere:
9
+    Code: WTFPL, textures: CC BY-SA
10
+
11
+Some textures taken from 3d_armor mod
12
+	these files are directly from the 3d_armor mod:
13
+		textures/walking_light_helmet_diamond.png
14
+		textures/walking_light_helmet_diamond_preview.png
15
+	parts of the following files came from 3d_armor's "3d_armor_inv_helmet_diamond.png": 
16
+		textures/walking_light_inv_helmet_diamond.png
17
+		textures/walking_light_inv_helmet_diamond.xcf
18
+
19
+	License Textures: 2013 Ryan Jones - CC-BY-SA
20
+
21
+	see 3d_armor mod here
22
+	https://forum.minetest.net/viewtopic.php?f=11&t=4654
23
+	https://github.com/stujones11/minetest-3d_armor
24
+
... ...
@@ -1,125 +1,528 @@
1
+-- list of all players seen by minetest.register_on_joinplayer
1 2
 local players = {}
3
+-- all player positions last time light was updated: {player_name : {x, y, z}}
2 4
 local player_positions = {}
5
+-- all light positions of light that currently is created {player_name : {i: {x, y, z}}
6
+local light_positions = {}
7
+-- last item seen wielded by players
3 8
 local last_wielded = {}
4 9
 
10
+-- toggles debug mode
11
+local walking_light_debug = false
12
+-- name of light node, changed by toggling debug mode
13
+local walking_light_node = nil
14
+
15
+-- initialize walking light
16
+walking_light = {}
17
+
18
+-- list of items that use walking light
19
+local light_items = {
20
+	"default:torch", "walking_light:pick_mese",
21
+	"walking_light:helmet_diamond", "walking_light:megatorch"
22
+}
23
+
24
+function walking_light.addLightItem(item)
25
+	for I in pairs(light_items) do
26
+		if item == light_items[I] then
27
+			minetest.log("warning", "[walking_light] \"" .. item .. "\" is already light item.")
28
+			return
29
+		end
30
+	end
31
+	
32
+	table.insert(light_items, -1, item)
33
+end
34
+
35
+function walking_light.getLightItems()
36
+	return light_items
37
+end
38
+
39
+
40
+-- from http://lua-users.org/wiki/IteratorsTutorial
41
+-- useful for removing things from a table because removing from the middle makes it skip elements otherwise
42
+function ripairs(t)
43
+  local function ripairs_it(t,i)
44
+    i=i-1
45
+    local v=t[i]
46
+    if v==nil then return v end
47
+    return i,v
48
+  end
49
+  return ripairs_it, t, #t+1
50
+end
51
+
52
+-- formats a vector with shorter output than dump
53
+local function dumppos(pos)
54
+	if pos == nil then
55
+		return "nil"
56
+	end
57
+	local x = "nil"
58
+	if pos.x then
59
+		x = pos.x
60
+	end
61
+	local y = "nil"
62
+	if pos.y then
63
+		y = pos.y
64
+	end
65
+	local z = "nil"
66
+	if pos.z then
67
+		z = pos.z
68
+	end
69
+
70
+	return "(" .. x .. "," .. y .. "," .. z .. ")"
71
+end
72
+
73
+-- formats a table containing vectors with shorter output than dump
74
+local function dumppostable(t)
75
+	if t == nil then
76
+		return "nil"
77
+	end
78
+	if #t == 0 then
79
+		return "0{}"
80
+	end
81
+
82
+	ret = #t .. "{\n"
83
+	for i,pos in ipairs(t) do
84
+		ret = ret .. "    " .. dumppos(pos) .. "\n"
85
+	end
86
+	ret = ret .. "}"
87
+	return ret
88
+end
89
+
90
+function mt_get_node_or_nil(pos)
91
+	if pos == nil then
92
+		print("ERROR: walking_light.mt_get_node_or_nil(), pos is nil")
93
+		print(debug.traceback("Current Callstack:\n"))
94
+		return nil
95
+	end
96
+	return minetest.get_node_or_nil(pos)
97
+end
98
+
99
+function mt_add_node(pos, sometable)
100
+	if pos == nil then
101
+		print("ERROR: walking_light.mt_add_node(), pos is nil")
102
+		print(debug.traceback("Current Callstack:\n"))
103
+		return nil
104
+	end
105
+	if sometable == nil then
106
+		print("ERROR: walking_light.mt_add_node(), sometable is nil")
107
+		print(debug.traceback("Current Callstack:\n"))
108
+		return nil
109
+	end
110
+	minetest.add_node(pos,sometable)
111
+end
112
+
5 113
 function round(num) 
6 114
 	return math.floor(num + 0.5) 
7 115
 end
8 116
 
117
+local function poseq(pos1, pos2)
118
+	if pos1 == nil and pos2 == nil then
119
+		return true
120
+	end
121
+	if pos1 == nil or pos2 == nil then
122
+		return false
123
+	end
124
+	return pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z
125
+end
126
+
127
+-- return true if the player moved since last player_positions update
128
+local function player_moved(player)
129
+	local player_name = player:get_player_name()
130
+	local pos = player:getpos()
131
+	local rounded_pos = vector.round(pos)
132
+	local oldpos = player_positions[player_name]
133
+	if oldpos == nil or not poseq(rounded_pos, oldpos) then
134
+		-- if oldpos is nil, we assume they just logged in, so consider them moved
135
+--		print("DEBUG: walking_light, player_moved(); moved = true; rounded_pos = " .. dumppos(rounded_pos) .. ", oldpos = " .. dumppos(oldpos))
136
+		return true
137
+	end
138
+--	print("DEBUG: walking_light, player_moved(); moved = false; rounded_pos = " .. dumppos(rounded_pos) .. ", oldpos = " .. dumppos(oldpos))
139
+	return false
140
+end
141
+
142
+-- same as table.remove(t,remove_pos), but uses poseq instead of comparing references (does lua have comparator support, so this isn't needed?)
143
+local function table_remove_pos(t, remove_pos)
144
+--	local DEBUG_oldsize = #t
145
+
146
+	for i,pos in ipairs(t) do
147
+		if poseq(pos, remove_pos) then
148
+			table.remove(t, i)
149
+			break
150
+		end
151
+	end
152
+
153
+--	local DEBUG_newsize = #t
154
+--	print("DEBUG: walking_light.table_remove_pos(), oldsize = " .. DEBUG_oldsize .. ", newsize = " .. DEBUG_newsize)
155
+end
156
+
157
+-- same as t[remove_pos], but uses poseq instead of comparing references (does lua have comparator support, so this isn't needed?)
158
+local function table_contains_pos(t, remove_pos)
159
+	for i,pos in ipairs(t) do
160
+		if poseq(pos, remove_pos) then
161
+			return true
162
+		end
163
+	end
164
+	return false
165
+end
166
+
167
+-- same as table.insert(t,pos) but makes sure it is not duplicated
168
+local function table_insert_pos(t, pos)
169
+	if not table_contains_pos( pos ) then
170
+		table.insert(t, pos)
171
+	end
172
+end
173
+
174
+local function is_light(node)
175
+	if node ~= nil and ( node.name == "walking_light:light" or node.name == "walking_light:light_debug" ) then
176
+		return true
177
+	end
178
+	return false
179
+end
180
+    
181
+-- removes light at the given position
182
+-- player is optional
183
+local function remove_light(player, pos)
184
+	local player_name
185
+	if player then
186
+		player_name = player:get_player_name()
187
+	end
188
+	local node = mt_get_node_or_nil(pos)
189
+	if is_light(node) then
190
+		mt_add_node(pos,{type="node",name="air"})
191
+		if player_name then
192
+			table_remove_pos(light_positions[player_name], pos)
193
+		end
194
+	else
195
+		if node ~= nil then
196
+			print("WARNING: walking_light.remove_light(), pos = " .. dumppos(pos) .. ", tried to remove light but node was " .. node.name)
197
+			table_remove_pos(light_positions[player_name], pos)
198
+		else
199
+			print("WARNING: walking_light.remove_light(), pos = " .. dumppos(pos) .. ", tried to remove light but node was nil")
200
+		end
201
+	end
202
+end
203
+
204
+-- removes all light owned by a player
205
+local function remove_light_player(player)
206
+	local player_name = player:get_player_name()
207
+
208
+    for i,old_pos in ripairs(light_positions[player_name]) do
209
+		if old_pos then
210
+--			print("DEBUG: walking_light.remove_light_player(), removing old light; old_pos = " .. dumppos(old_pos))
211
+			remove_light(player, old_pos)
212
+		end
213
+	end
214
+--	print("DEBUG: walking_light.remove_light_player(), done; light_positions = " .. dumppostable(light_positions[player_name]))
215
+end
216
+
217
+local function can_add_light(pos)
218
+	local node  = mt_get_node_or_nil(pos)
219
+	if node == nil or node.name == "air" then
220
+--		print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", true")
221
+		return true
222
+	elseif is_light(node) then
223
+--		print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", true")
224
+		return true
225
+	end
226
+--	print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", false")
227
+	return false
228
+end
229
+
230
+-- old function returns pos instead of table, for only one position
231
+local function pick_light_position_regular(player, pos)
232
+	if can_add_light(pos) then
233
+		return {pos}
234
+	end
235
+
236
+	local pos2
237
+
238
+	-- if pos is not possible, try the old player position first, to make it more likely that it has a line of sight
239
+	local player_name = player:get_player_name()
240
+	local oldplayerpos = player_positions[player_name]
241
+	if oldplayerpos and can_add_light( vector.new(oldplayerpos.x, oldplayerpos.y + 1, oldplayerpos.z) ) then
242
+		return oldplayerpos 
243
+	end
244
+
245
+	-- if not, try all positions around the pos
246
+	pos2 = vector.new(pos.x + 1, pos.y, pos.z)
247
+	if can_add_light( pos2 ) then
248
+		return {pos2}
249
+	end
250
+
251
+	pos2 = vector.new(pos.x - 1, pos.y, pos.z)
252
+	if can_add_light( pos2 ) then
253
+		return {pos2}
254
+	end
255
+
256
+	pos2 = vector.new(pos.x, pos.y, pos.z + 1)
257
+	if can_add_light( pos2 ) then
258
+		return {pos2}
259
+	end
260
+
261
+	pos2 = vector.new(pos.x, pos.y, pos.z - 1)
262
+	if can_add_light( pos2 ) then
263
+		return {pos2}
264
+	end
265
+
266
+	pos2 = vector.new(pos.x, pos.y + 1, pos.z)
267
+	if can_add_light( pos2 ) then
268
+		return {pos2}
269
+	end
270
+
271
+	pos2 = vector.new(pos.x, pos.y - 1, pos.z)
272
+	if can_add_light( pos2 ) then
273
+		return {pos2}
274
+	end
275
+
276
+	return nil
277
+end
278
+
279
+-- new function, returns table
280
+local function pick_light_position_radius(player, pos, ret, radius)
281
+	local pos2
282
+	local step = 4
283
+	local unstep = 1/step
284
+
285
+	for x = pos.x - radius, pos.x + radius, step do
286
+		for y = pos.y - radius, pos.y + radius, step do
287
+			for z = pos.z - radius, pos.z + radius, step do
288
+				pos2 = vector.new(round(x*unstep)*step, round(y*unstep)*step, round(z*unstep)*step)
289
+				distance = math.sqrt(math.pow(pos.x - x, 2) + math.pow(pos.y - y, 2) + math.pow(pos.z - z, 2))
290
+				if distance <= radius and can_add_light( pos2 ) then
291
+					table.insert(ret, pos2)
292
+				end
293
+			end
294
+		end
295
+	end
296
+
297
+	return ret
298
+end
299
+
300
+local function pick_light_position_mega(player, pos)
301
+	local ret = {}
302
+
303
+	if can_add_light(pos) then
304
+		table.insert(ret, pos)
305
+	end
306
+	pick_light_position_radius(player, pos, ret, 10)
307
+
308
+	return ret
309
+end
310
+
311
+local function pick_light_position(player, pos, light_item)
312
+	if light_item == "walking_light:megatorch" then
313
+		return pick_light_position_mega(player, pos)
314
+	end
315
+	return pick_light_position_regular(player, pos)
316
+end
317
+
318
+-- adds light at the given position
319
+local function add_light(player, pos)
320
+	local player_name = player:get_player_name()
321
+	local node  = mt_get_node_or_nil(pos)
322
+	if node == nil then
323
+		-- don't do anything for nil blocks... they are non-loaded blocks, so we don't want to overwrite anything there
324
+--		print("DEBUG: walking_light.add_light(), node is nil, pos = " .. dumppos(pos))
325
+		return false
326
+	elseif node.name == "air" then
327
+		-- when the node that is already there is air, add light
328
+		mt_add_node(pos,{type="node",name=walking_light_node})
329
+		if not table_contains_pos(light_positions[player_name], pos) then
330
+			table_insert_pos(light_positions[player_name], pos)
331
+		end
332
+
333
+--		if node then
334
+--			print("DEBUG: add_light(), node.name = " .. node.name .. ", pos = " .. dumppos(pos))
335
+--		else
336
+--			print("DEBUG: add_light(), node.name = nil, pos = " .. dumppos(pos))
337
+--		end
338
+		return true
339
+	elseif is_light(node) then
340
+		-- no point in adding light where it is already, but we should assign it to the player so it gets removed (in case it has no player)
341
+--		print("DEBUG: add_light(), not adding; node.name = " .. node.name .. ", pos = " .. dumppos(pos))
342
+
343
+		if not table_contains_pos(light_positions[player_name], pos) then
344
+			table_insert_pos(light_positions[player_name], pos)
345
+		end
346
+
347
+		return true
348
+	end
349
+--	print("DEBUG: add_light(), not adding; node.name = " .. node.name)
350
+	return false
351
+end
352
+
353
+-- updates all the light around the player, depending on what they are wielding
354
+local function update_light_player(player)
355
+	-- if there is no player, there can be no update
356
+	if not player then
357
+		return
358
+	end
359
+
360
+	-- figure out if they wield light; this will be nil if not
361
+	local wielded_item = get_wielded_light_item(player)
362
+
363
+	local player_name = player:get_player_name()
364
+	local pos = player:getpos()
365
+	local rounded_pos = vector.round(pos)
366
+
367
+	-- check for a nil node where the player is; if it is nil, we assume the block is not loaded, so we return without updating player_positions
368
+	-- that way, it should add light next step
369
+	local node  = mt_get_node_or_nil(rounded_pos)
370
+	if node == nil then
371
+		return
372
+	end
373
+
374
+	if not player_moved(player) and wielded_item == last_wielded[player_name] then
375
+		-- no update needed if the wiedled light item is the same as before (including nil), and the player didn't move
376
+		return
377
+	end
378
+	last_wielded[player_name] = wielded_item;
379
+
380
+	local wantlightpos = nil
381
+	local wantpos = vector.new(rounded_pos.x, rounded_pos.y + 1, rounded_pos.z)
382
+	if wielded_item then
383
+		-- decide where light should be
384
+		wantlightpos = pick_light_position(player, wantpos, wielded_item)
385
+--		print("DEBUG: walking_light update_light_player(); wantpos = " .. dumppos(wantpos) .. ", wantlightpos = " .. dumppos(wantlightpos))
386
+	end
387
+
388
+	if wielded_item and wantlightpos then
389
+		-- add light that isn't already there
390
+		for i,newpos in ipairs(wantlightpos) do
391
+			add_light(player, newpos)
392
+		end
393
+	end
394
+
395
+	-- go through all light owned by the player to remove all but what should be kept
396
+    for i,oldlightpos in ripairs(light_positions[player_name]) do
397
+        if not wantlightpos or oldlightpos and oldlightpos.x and not table_contains_pos(wantlightpos, oldlightpos) then
398
+			remove_light(player, oldlightpos)
399
+        end
400
+    end
401
+
402
+	player_positions[player_name] = vector.round(pos)
403
+
404
+--	print("DEBUG: walking_light.update_light_player(): wantlightpos = " .. dumppostable(wantlightpos) .. ", light_positions = " .. dumppostable(light_positions[player_name]))
405
+end
406
+
407
+local function update_light_all()
408
+	-- go through all players to check
409
+	for i,player_name in ipairs(players) do
410
+		local player = minetest.get_player_by_name(player_name)
411
+		update_light_player(player)
412
+	end
413
+end
414
+
415
+-- return true if item is a light item
416
+function is_light_item(item)
417
+	for I in pairs(light_items) do
418
+		if item == light_items[I] then
419
+			return true
420
+		end
421
+	end
422
+	return false
423
+end
424
+
425
+-- returns a string, the name of the item found that is a light item
426
+function get_wielded_light_item(player)
427
+	local wielded_item = player:get_wielded_item():get_name()
428
+	if is_light_item(wielded_item) then
429
+		return wielded_item
430
+	end
431
+
432
+	-- check equipped armor - requires unified_inventory maybe
433
+	local player_name = player:get_player_name()
434
+	if player_name then
435
+		local armor_inv = minetest.get_inventory({type="detached", name=player_name.."_armor"})
436
+		if armor_inv then
437
+--            print( dump(armor_inv:get_lists()) )
438
+			local item_name = "walking_light:helmet_diamond"
439
+			local stack = ItemStack(item_name)
440
+			if armor_inv:contains_item("armor", stack) then
441
+				return item_name
442
+			end
443
+		end
444
+	end
445
+
446
+	return nil
447
+end
448
+
449
+-- return true if player is wielding a light item
450
+function wielded_light(player)
451
+	return get_wielded_light_item(player) ~= nil
452
+end
453
+
9 454
 minetest.register_on_joinplayer(function(player)
10 455
 	local player_name = player:get_player_name()
11 456
 	table.insert(players, player_name)
12
-	last_wielded[player_name] = player:get_wielded_item():get_name()
457
+	last_wielded[player_name] = get_wielded_light_item(player)
13 458
 	local pos = player:getpos()
14
-	local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
15
-	local wielded_item = player:get_wielded_item():get_name()
16
-	if wielded_item ~= "default:torch" and wielded_item ~= "walking_light:pick_mese" then
17
-		-- Neuberechnung des Lichts erzwingen
18
-		minetest.env:add_node(rounded_pos,{type="node",name="default:cobble"})
19
-		minetest.env:add_node(rounded_pos,{type="node",name="air"})
20
-	end
21
-	player_positions[player_name] = {}
22
-	player_positions[player_name]["x"] = rounded_pos.x;
23
-	player_positions[player_name]["y"] = rounded_pos.y;
24
-	player_positions[player_name]["z"] = rounded_pos.z;
459
+	player_positions[player_name] = nil
460
+	light_positions[player_name] = {}
461
+	update_light_player(player)
25 462
 end)
26 463
 
27 464
 minetest.register_on_leaveplayer(function(player)
28 465
 	local player_name = player:get_player_name()
29 466
 	for i,v in ipairs(players) do
30
-		if v == player_name then 
467
+		if v == player_name then
31 468
 			table.remove(players, i)
32
-			last_wielded[player_name] = nil
33
-			-- Neuberechnung des Lichts erzwingen
34
-			local pos = player:getpos()
35
-			local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
36
-			minetest.env:add_node(rounded_pos,{type="node",name="default:cobble"})
37
-			minetest.env:add_node(rounded_pos,{type="node",name="air"})
38
-			player_positions[player_name]["x"] = nil
39
-			player_positions[player_name]["y"] = nil
40
-			player_positions[player_name]["z"] = nil
41
-			player_positions[player_name]["m"] = nil
42
-			player_positions[player_name] = nil
43 469
 		end
44 470
 	end
471
+	last_wielded[player_name] = false
472
+	remove_light_player(player)
473
+	player_positions[player_name]=nil
45 474
 end)
46 475
 
47 476
 minetest.register_globalstep(function(dtime)
48 477
 	for i,player_name in ipairs(players) do
49
-		local player = minetest.env:get_player_by_name(player_name)
50
-		local wielded_item = player:get_wielded_item():get_name()
51
-		if wielded_item == "default:torch" or wielded_item == "walking_light:pick_mese" then
52
-			-- Fackel ist in der Hand
53
-			local pos = player:getpos()
54
-			local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
55
-			if (last_wielded[player_name] ~= "default:torch" and last_wielded[player_name] ~= "walking_light:pick_mese") or (player_positions[player_name]["x"] ~= rounded_pos.x or player_positions[player_name]["y"] ~= rounded_pos.y or player_positions[player_name]["z"] ~= rounded_pos.z) then
56
-				-- Fackel gerade in die Hand genommen oder zu neuem Node bewegt
57
-				local is_air  = minetest.env:get_node_or_nil(rounded_pos)
58
-				if is_air == nil or (is_air ~= nil and (is_air.name == "air" or is_air.name == "walking_light:light")) then
59
-					-- wenn an aktueller Position "air" ist, Fackellicht setzen
60
-					minetest.env:add_node(rounded_pos,{type="node",name="walking_light:light"})
61
-				end
62
-				if (player_positions[player_name]["x"] ~= rounded_pos.x or player_positions[player_name]["y"] ~= rounded_pos.y or player_positions[player_name]["z"] ~= rounded_pos.z) then
63
-					-- wenn Position ge�nder, dann altes Licht l�schen
64
-					local old_pos = {x=player_positions[player_name]["x"], y=player_positions[player_name]["y"], z=player_positions[player_name]["z"]}
65
-					-- Neuberechnung des Lichts erzwingen
66
-					local is_light = minetest.env:get_node_or_nil(old_pos)
67
-					if is_light ~= nil and is_light.name == "walking_light:light" then
68
-						minetest.env:add_node(old_pos,{type="node",name="default:cobble"})
69
-						minetest.env:add_node(old_pos,{type="node",name="air"})
70
-					end
71
-				end
72
-				-- gemerkte Position ist nun die gerundete neue Position
73
-				player_positions[player_name]["x"] = rounded_pos.x
74
-				player_positions[player_name]["y"] = rounded_pos.y
75
-				player_positions[player_name]["z"] = rounded_pos.z
76
-			end
77
-
78
-			last_wielded[player_name] = wielded_item;
79
-		elseif last_wielded[player_name] == "default:torch" or last_wielded[player_name] == "walking_light:pick_mese" then
80
-			-- Fackel nicht in der Hand, aber beim letzten Durchgang war die Fackel noch in der Hand
81
-			local pos = player:getpos()
82
-			local rounded_pos = {x=round(pos.x),y=round(pos.y)+1,z=round(pos.z)}
83
-			repeat
84
-				local is_light  = minetest.env:get_node_or_nil(rounded_pos)
85
-				if is_light ~= nil and is_light.name == "walking_light:light" then
86
-					-- minetest.env:remove_node(rounded_pos)
87
-					-- Erzwinge Neuberechnung des Lichts
88
-					minetest.env:add_node(rounded_pos,{type="node",name="default:cobble"})
89
-					minetest.env:add_node(rounded_pos,{type="node",name="air"})
90
-				end
91
-			until minetest.env:get_node_or_nil(rounded_pos) ~= "walking_light:light"
92
-			local old_pos = {x=player_positions[player_name]["x"], y=player_positions[player_name]["y"], z=player_positions[player_name]["z"]}
93
-			repeat
94
-				is_light  = minetest.env:get_node_or_nil(old_pos)
95
-				if is_light ~= nil and is_light.name == "walking_light:light" then
96
-					-- minetest.env:remove_node(old_pos)
97
-					-- Erzwinge Neuberechnung des Lichts
98
-					minetest.env:add_node(old_pos,{type="node",name="default:cobble"})
99
-					minetest.env:add_node(old_pos,{type="node",name="air"})
100
-				end
101
-			until minetest.env:get_node_or_nil(old_pos) ~= "walking_light:light"
102
-			last_wielded[player_name] = wielded_item
478
+		local player = minetest.get_player_by_name(player_name)
479
+		if player ~= nil then
480
+			update_light_player(player)
481
+		else
482
+			table.remove(players, i)
103 483
 		end
104 484
 	end
105 485
 end)
106 486
 
487
+minetest.register_node("walking_light:light_debug", {
488
+	drawtype = "glasslike",
489
+	tiles = {"walking_light_debug.png"},
490
+	inventory_image = minetest.inventorycube("walking_light.png"),
491
+	paramtype = "light",
492
+	walkable = false,
493
+	is_ground_content = true,
494
+	sunlight_propagates = true,
495
+	light_source = 14,
496
+	selection_box = {
497
+		type = "fixed",
498
+		fixed = {0, 0, 0, 0, 0, 0},
499
+	},
500
+})
501
+
107 502
 minetest.register_node("walking_light:light", {
108 503
 	drawtype = "glasslike",
109
-	tile_images = {"walking_light.png"},
110
-	-- tile_images = {"walking_light_debug.png"},
504
+	tiles = {"walking_light.png"},
111 505
 	inventory_image = minetest.inventorycube("walking_light.png"),
112 506
 	paramtype = "light",
113 507
 	walkable = false,
114 508
 	is_ground_content = true,
115
-	light_propagates = true,
116 509
 	sunlight_propagates = true,
117 510
 	light_source = 14,
118 511
 	selection_box = {
119
-        type = "fixed",
120
-        fixed = {0, 0, 0, 0, 0, 0},
121
-    },
512
+		type = "fixed",
513
+		fixed = {0, 0, 0, 0, 0, 0},
514
+	},
122 515
 })