Browse code

Merge branch 'walking_light' of emorrp1/ocd3 into master

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