From f2a9e17a8128b922ee400243108d5f92373a9fe2 Mon Sep 17 00:00:00 2001 From: AntumDeluge Date: Mon, 1 Aug 2016 11:05:44 -0700 Subject: [PATCH] Add "walking_light" mod. --- README.md | 2 + mods/player/walking_light/README.md | 24 + mods/player/walking_light/init.lua | 626 ++++++++++++++++++ .../walking_light/textures/walking_light.png | Bin 0 -> 128 bytes .../textures/walking_light_debug.png | Bin 0 -> 219 bytes .../textures/walking_light_helmet_diamond.png | Bin 0 -> 524 bytes .../walking_light_helmet_diamond_preview.png | Bin 0 -> 902 bytes .../walking_light_inv_helmet_diamond.png | Bin 0 -> 371 bytes .../walking_light_inv_helmet_diamond.xcf | Bin 0 -> 1947 bytes .../textures/walking_light_mesepick.png | Bin 0 -> 402 bytes 10 files changed, 652 insertions(+) create mode 100644 mods/player/walking_light/README.md create mode 100644 mods/player/walking_light/init.lua create mode 100644 mods/player/walking_light/textures/walking_light.png create mode 100644 mods/player/walking_light/textures/walking_light_debug.png create mode 100644 mods/player/walking_light/textures/walking_light_helmet_diamond.png create mode 100644 mods/player/walking_light/textures/walking_light_helmet_diamond_preview.png create mode 100644 mods/player/walking_light/textures/walking_light_inv_helmet_diamond.png create mode 100644 mods/player/walking_light/textures/walking_light_inv_helmet_diamond.xcf create mode 100644 mods/player/walking_light/textures/walking_light_mesepick.png diff --git a/README.md b/README.md index 8b054670..7c52ed6d 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ The following mods are also included: * shields ([3d_armor modpack][3d_armor]) * technic_armor ([3d_armor modpack][3d_armor]) * [unified_inventory][] ([LGPL/WTFPL](mods/player/unified_inventory/README.md)) + * [walking_light][] ([WTFPL / CC-BY-SA](mods/player/walking_light/README.md)) * [wardrobe][] ([WTFPL](mods/player/wardrobe/README.txt)) * wieldview ([3d_armor modpack][3d_armor]) * [technic (modpack)][technic] ([LGPL](mods/technic/README.md)) @@ -118,6 +119,7 @@ The following mods are also included: [unified_inventory]: https://forum.minetest.net/viewtopic.php?id=3933 [unifieddyes]: https://forum.minetest.net/viewtopic.php?t=2178 [vines]: https://forum.minetest.net/viewtopic.php?f=11&t=2344 +[walking_light]: https://github.com/petermaloney/walking_light [wardrobe]: https://forum.minetest.net/viewtopic.php?id=9680 [weather]: https://forum.minetest.net/viewtopic.php?t=5245 [workbench]: https://forum.minetest.net/viewtopic.php?t=14085 diff --git a/mods/player/walking_light/README.md b/mods/player/walking_light/README.md new file mode 100644 index 00000000..e79e14f8 --- /dev/null +++ b/mods/player/walking_light/README.md @@ -0,0 +1,24 @@ +minetest mod walking_light + +forked from 0.6 https://forum.minetest.net/viewtopic.php?f=11&t=2621&hilit=walking+light + +Licensing: +========== + +If not noted elsewhere: + Code: WTFPL, textures: CC BY-SA + +Some textures taken from 3d_armor mod + these files are directly from the 3d_armor mod: + textures/walking_light_helmet_diamond.png + textures/walking_light_helmet_diamond_preview.png + parts of the following files came from 3d_armor's "3d_armor_inv_helmet_diamond.png": + textures/walking_light_inv_helmet_diamond.png + textures/walking_light_inv_helmet_diamond.xcf + + License Textures: 2013 Ryan Jones - CC-BY-SA + + see 3d_armor mod here + https://forum.minetest.net/viewtopic.php?f=11&t=4654 + https://github.com/stujones11/minetest-3d_armor + diff --git a/mods/player/walking_light/init.lua b/mods/player/walking_light/init.lua new file mode 100644 index 00000000..aa25214f --- /dev/null +++ b/mods/player/walking_light/init.lua @@ -0,0 +1,626 @@ +-- list of all players seen by minetest.register_on_joinplayer +local players = {} +-- all player positions last time light was updated: {player_name : {x, y, z}} +local player_positions = {} +-- all light positions of light that currently is created {player_name : {i: {x, y, z}} +local light_positions = {} +-- last item seen wielded by players +local last_wielded = {} + +-- from http://lua-users.org/wiki/IteratorsTutorial +-- useful for removing things from a table because removing from the middle makes it skip elements otherwise +function ripairs(t) + local function ripairs_it(t,i) + i=i-1 + local v=t[i] + if v==nil then return v end + return i,v + end + return ripairs_it, t, #t+1 +end + +-- formats a vector with shorter output than dump +local function dumppos(pos) + if pos == nil then + return "nil" + end + local x = "nil" + if pos.x then + x = pos.x + end + local y = "nil" + if pos.y then + y = pos.y + end + local z = "nil" + if pos.z then + z = pos.z + end + + return "(" .. x .. "," .. y .. "," .. z .. ")" +end + +-- formats a table containing vectors with shorter output than dump +local function dumppostable(t) + if t == nil then + return "nil" + end + if #t == 0 then + return "0{}" + end + + ret = #t .. "{\n" + for i,pos in ipairs(t) do + ret = ret .. " " .. dumppos(pos) .. "\n" + end + ret = ret .. "}" + return ret +end + +function mt_get_node_or_nil(pos) + if pos == nil then + print("ERROR: walking_light.mt_get_node_or_nil(), pos is nil") + print(debug.traceback("Current Callstack:\n")) + return nil + end + return minetest.env:get_node_or_nil(pos) +end + +function mt_add_node(pos, sometable) + if pos == nil then + print("ERROR: walking_light.mt_add_node(), pos is nil") + print(debug.traceback("Current Callstack:\n")) + return nil + end + if sometable == nil then + print("ERROR: walking_light.mt_add_node(), sometable is nil") + print(debug.traceback("Current Callstack:\n")) + return nil + end + minetest.env:add_node(pos,sometable) +end + +function round(num) + return math.floor(num + 0.5) +end + +local function poseq(pos1, pos2) + if pos1 == nil and pos2 == nil then + return true + end + if pos1 == nil or pos2 == nil then + return false + end + return pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z +end + +-- return true if the player moved since last player_positions update +local function player_moved(player) + local player_name = player:get_player_name() + local pos = player:getpos() + local rounded_pos = vector.round(pos) + local oldpos = player_positions[player_name] + if oldpos == nil or not poseq(rounded_pos, oldpos) then + -- if oldpos is nil, we assume they just logged in, so consider them moved +-- print("DEBUG: walking_light, player_moved(); moved = true; rounded_pos = " .. dumppos(rounded_pos) .. ", oldpos = " .. dumppos(oldpos)) + return true + end +-- print("DEBUG: walking_light, player_moved(); moved = false; rounded_pos = " .. dumppos(rounded_pos) .. ", oldpos = " .. dumppos(oldpos)) + return false +end + +-- same as table.remove(t,remove_pos), but uses poseq instead of comparing references (does lua have comparator support, so this isn't needed?) +local function table_remove_pos(t, remove_pos) +-- local DEBUG_oldsize = #t + + for i,pos in ipairs(t) do + if poseq(pos, remove_pos) then + table.remove(t, i) + break + end + end + +-- local DEBUG_newsize = #t +-- print("DEBUG: walking_light.table_remove_pos(), oldsize = " .. DEBUG_oldsize .. ", newsize = " .. DEBUG_newsize) +end + +-- same as t[remove_pos], but uses poseq instead of comparing references (does lua have comparator support, so this isn't needed?) +local function table_contains_pos(t, remove_pos) + for i,pos in ipairs(t) do + if poseq(pos, remove_pos) then + return true + end + end + return false +end + +-- same as table.insert(t,pos) but makes sure it is not duplicated +local function table_insert_pos(t, pos) + if not table_contains_pos( pos ) then + table.insert(t, pos) + end +end + +-- removes light at the given position +-- player is optional +local function remove_light(player, pos) + local player_name + if player then + player_name = player:get_player_name() + end + local node = mt_get_node_or_nil(pos) + if node ~= nil and node.name == "walking_light:light" then + mt_add_node(pos,{type="node",name="walking_light:clear"}) + mt_add_node(pos,{type="node",name="air"}) + if player_name then + table_remove_pos(light_positions[player_name], pos) + end + else + if node ~= nil then + print("WARNING: walking_light.remove_light(), pos = " .. dumppos(pos) .. ", tried to remove light but node was " .. node.name) + table_remove_pos(light_positions[player_name], pos) + else + print("WARNING: walking_light.remove_light(), pos = " .. dumppos(pos) .. ", tried to remove light but node was nil") + end + end +end + +-- removes all light owned by a player +local function remove_light_player(player) + local player_name = player:get_player_name() + + for i,old_pos in ripairs(light_positions[player_name]) do + if old_pos then +-- print("DEBUG: walking_light.remove_light_player(), removing old light; old_pos = " .. dumppos(old_pos)) + remove_light(player, old_pos) + end + end + print("DEBUG: walking_light.remove_light_player(), done; light_positions = " .. dumppostable(light_positions[player_name])) +end + +local function can_add_light(pos) + local node = mt_get_node_or_nil(pos) + if node == nil or node.name == "air" then +-- print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", true") + return true + elseif node.name == "walking_light:light" then +-- print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", true") + return true + end +-- print("walking_light can_add_light(), pos = " .. dumppos(pos) .. ", false") + return false +end + +-- old function returns pos instead of table, for only one position +local function pick_light_position_regular(player, pos) + if can_add_light(pos) then + return {pos} + end + + local pos2 + + -- if pos is not possible, try the old player position first, to make it more likely that it has a line of sight + local player_name = player:get_player_name() + local oldplayerpos = player_positions[player_name] + if oldplayerpos and can_add_light( vector.new(oldplayerpos.x, oldplayerpos.y + 1, oldplayerpos.z) ) then + return oldplayerpos + end + + -- if not, try all positions around the pos + pos2 = vector.new(pos.x + 1, pos.y, pos.z) + if can_add_light( pos2 ) then + return {pos2} + end + + pos2 = vector.new(pos.x - 1, pos.y, pos.z) + if can_add_light( pos2 ) then + return {pos2} + end + + pos2 = vector.new(pos.x, pos.y, pos.z + 1) + if can_add_light( pos2 ) then + return {pos2} + end + + pos2 = vector.new(pos.x, pos.y, pos.z - 1) + if can_add_light( pos2 ) then + return {pos2} + end + + pos2 = vector.new(pos.x, pos.y + 1, pos.z) + if can_add_light( pos2 ) then + return {pos2} + end + + pos2 = vector.new(pos.x, pos.y - 1, pos.z) + if can_add_light( pos2 ) then + return {pos2} + end + + return nil +end + +-- new function, returns table +local function pick_light_position_radius(player, pos, ret, radius) + local pos2 + local step = 4 + local unstep = 1/step + + for x = pos.x - radius, pos.x + radius, step do + for y = pos.y - radius, pos.y + radius, step do + for z = pos.z - radius, pos.z + radius, step do + pos2 = vector.new(round(x*unstep)*step, round(y*unstep)*step, round(z*unstep)*step) + distance = math.sqrt(math.pow(pos.x - x, 2) + math.pow(pos.y - y, 2) + math.pow(pos.z - z, 2)) + if distance <= radius and can_add_light( pos2 ) then + table.insert(ret, pos2) + end + end + end + end + + return ret +end + +local function pick_light_position_mega(player, pos) + local ret = {} + + if can_add_light(pos) then + table.insert(ret, pos) + end + pick_light_position_radius(player, pos, ret, 10) + + return ret +end + +local function pick_light_position(player, pos, light_item) + if light_item == "walking_light:megatorch" then + return pick_light_position_mega(player, pos) + end + return pick_light_position_regular(player, pos) +end + +-- adds light at the given position +local function add_light(player, pos) + local player_name = player:get_player_name() + local node = mt_get_node_or_nil(pos) + if node == nil then + -- don't do anything for nil blocks... they are non-loaded blocks, so we don't want to overwrite anything there +-- print("DEBUG: walking_light.add_light(), node is nil, pos = " .. dumppos(pos)) + return false + elseif node.name == "air" then + -- when the node that is already there is air, add light + mt_add_node(pos,{type="node",name="walking_light:light"}) + if not table_contains_pos(light_positions[player_name], pos) then + table_insert_pos(light_positions[player_name], pos) + end + +-- if node then +-- print("DEBUG: add_light(), node.name = " .. node.name .. ", pos = " .. dumppos(pos)) +-- else +-- print("DEBUG: add_light(), node.name = nil, pos = " .. dumppos(pos)) +-- end + return true + elseif node.name == "walking_light:light" then + -- 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) +-- print("DEBUG: add_light(), not adding; node.name = " .. node.name .. ", pos = " .. dumppos(pos)) + + if not table_contains_pos(light_positions[player_name], pos) then + table_insert_pos(light_positions[player_name], pos) + end + + return true + end +-- print("DEBUG: add_light(), not adding; node.name = " .. node.name) + return false +end + +-- updates all the light around the player, depending on what they are wielding +local function update_light_player(player) + -- if there is no player, there can be no update + if not player then + return + end + + -- figure out if they wield light; this will be nil if not + local wielded_item = get_wielded_light_item(player) + + local player_name = player:get_player_name() + local pos = player:getpos() + local rounded_pos = vector.round(pos) + + -- 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 + -- that way, it should add light next step + local node = mt_get_node_or_nil(rounded_pos) + if node == nil then + return + end + + if not player_moved(player) and wielded_item == last_wielded[player_name] then + -- no update needed if the wiedled light item is the same as before (including nil), and the player didn't move + return + end + last_wielded[player_name] = wielded_item; + + local wantlightpos = nil + local wantpos = vector.new(rounded_pos.x, rounded_pos.y + 1, rounded_pos.z) + if wielded_item then + -- decide where light should be + wantlightpos = pick_light_position(player, wantpos, wielded_item) +-- print("DEBUG: walking_light update_light_player(); wantpos = " .. dumppos(wantpos) .. ", wantlightpos = " .. dumppos(wantlightpos)) + end + + if wielded_item and wantlightpos then + -- add light that isn't already there + for i,newpos in ipairs(wantlightpos) do + add_light(player, newpos) + end + end + + -- go through all light owned by the player to remove all but what should be kept + for i,oldlightpos in ripairs(light_positions[player_name]) do + if not wantlightpos or oldlightpos and oldlightpos.x and not table_contains_pos(wantlightpos, oldlightpos) then + remove_light(player, oldlightpos) + end + end + + player_positions[player_name] = vector.round(pos) + +-- print("DEBUG: walking_light.update_light_player(): wantlightpos = " .. dumppostable(wantlightpos) .. ", light_positions = " .. dumppostable(light_positions[player_name])) +end + +local function update_light_all() + -- go through all players to check + for i,player_name in ipairs(players) do + local player = minetest.env:get_player_by_name(player_name) + update_light_player(player) + end +end + +-- return true if item is a light item +function is_light_item(item) + if item == "default:torch" or item == "walking_light:pick_mese" + or item == "walking_light:helmet_diamond" + or item == "walking_light:megatorch" then + return true + end + return false +end + +-- returns a string, the name of the item found that is a light item +function get_wielded_light_item(player) + local wielded_item = player:get_wielded_item():get_name() + if is_light_item(wielded_item) then + return wielded_item + end + + -- check equipped armor - requires unified_inventory maybe + local player_name = player:get_player_name() + if player_name then + local armor_inv = minetest.get_inventory({type="detached", name=player_name.."_armor"}) + if armor_inv then +-- print( dump(armor_inv:get_lists()) ) + local item_name = "walking_light:helmet_diamond" + local stack = ItemStack(item_name) + if armor_inv:contains_item("armor", stack) then + return item_name + end + end + end + + return nil +end + +-- return true if player is wielding a light item +function wielded_light(player) + return get_wielded_light_item(player) ~= nil +end + +minetest.register_on_joinplayer(function(player) + local player_name = player:get_player_name() + table.insert(players, player_name) + last_wielded[player_name] = get_wielded_light_item(player) + local pos = player:getpos() + player_positions[player_name] = nil + light_positions[player_name] = {} + update_light_player(player) +end) + +minetest.register_on_leaveplayer(function(player) + local player_name = player:get_player_name() + for i,v in ipairs(players) do + if v == player_name then + table.remove(players, i) + end + end + last_wielded[player_name] = false + remove_light_player(player) + player_positions[player_name]=nil +end) + +minetest.register_globalstep(function(dtime) + for i,player_name in ipairs(players) do + local player = minetest.env:get_player_by_name(player_name) + if player ~= nil then + update_light_player(player) + else + table.remove(players, i) + end + end +end) + +minetest.register_node("walking_light:clear", { + drawtype = "glasslike", + tile_images = {"walking_light.png"}, + -- tile_images = {"walking_light_debug.png"}, + --inventory_image = minetest.inventorycube("walking_light.png"), + --paramtype = "light", + walkable = false, + --is_ground_content = true, + light_propagates = true, + sunlight_propagates = true, + --light_source = 13, + selection_box = { + type = "fixed", + fixed = {0, 0, 0, 0, 0, 0}, + }, +}) + +minetest.register_node("walking_light:light", { + drawtype = "glasslike", + tile_images = {"walking_light.png"}, + -- tile_images = {"walking_light_debug.png"}, + inventory_image = minetest.inventorycube("walking_light.png"), + paramtype = "light", + walkable = false, + is_ground_content = true, + light_propagates = true, + sunlight_propagates = true, + light_source = 13, + selection_box = { + type = "fixed", + fixed = {0, 0, 0, 0, 0, 0}, + }, +}) + +minetest.register_tool("walking_light:pick_mese", { + description = "Mese Pickaxe with light", + inventory_image = "walking_light_mesepick.png", + wield_image = "default_tool_mesepick.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=3, + groupcaps={ + cracky={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3}, + crumbly={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3}, + snappy={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3} + } + }, +}) + +minetest.register_tool("walking_light:helmet_diamond", { + description = "Diamond Helmet with light", + inventory_image = "walking_light_inv_helmet_diamond.png", + wield_image = "3d_armor_inv_helmet_diamond.png", + groups = {armor_head=15, armor_heal=12, armor_use=100}, + wear = 0, +}) + +minetest.register_node("walking_light:megatorch", { + description = "Megatorch", + drawtype = "torchlike", + tiles = { + { + name = "default_torch_on_floor_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0 + }, + }, + { + name="default_torch_on_ceiling_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0 + }, + }, + { + name="default_torch_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0 + }, + }, + }, + inventory_image = "default_torch_on_floor.png", + wield_image = "default_torch_on_floor.png", + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + is_ground_content = false, + walkable = false, + light_source = 13, + selection_box = { + type = "wallmounted", + wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1}, + wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1}, + wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1}, + }, + groups = {choppy=2,dig_immediate=3,flammable=1,attached_node=1}, + legacy_wallmounted = true, + --sounds = default.node_sound_defaults(), +}) + +minetest.register_craft({ + output = 'walking_light:pick_mese', + recipe = { + {'default:torch'}, + {'default:pick_mese'}, + } +}) + +minetest.register_craft({ + output = 'walking_light:helmet_diamond', + recipe = { + {'default:torch'}, + {'3d_armor:helmet_diamond'}, + } +}) + +minetest.register_craft({ + output = 'walking_light:megatorch', + recipe = { + {'default:torch', 'default:torch', 'default:torch'}, + {'default:torch', 'default:torch', 'default:torch'}, + {'default:torch', 'default:torch', 'default:torch'}, + } +}) + +minetest.register_chatcommand("mapclearlight", { + params = "", + description = "Remove walking_light:light from the area", + func = function(name, param) + if not minetest.check_player_privs(name, {server=true}) then + return false, "You need the server privilege to use mapclearlight" + end + + local pos = vector.round(minetest.get_player_by_name(name):getpos()) + local size = tonumber(param) or 40 + + point = minetest.find_node_near(pos, size/2, "walking_light:light") + while point do + remove_light(nil, point) + oldpoint = point + point = minetest.find_node_near(pos, size/2, "walking_light:light") + if poseq(oldpoint, point) then + return false, "Failed... infinite loop detected" + end + end + return true, "Done." + end, +}) + +minetest.register_chatcommand("mapaddlight", { + params = "", + description = "Add walking_light:light to a position, without a player owning it", + func = function(name, param) + if not minetest.check_player_privs(name, {server=true}) then + return false, "You need the server privilege to use mapaddlight" + end + + local pos = vector.round(minetest.get_player_by_name(name):getpos()) + pos = vector.new(pos.x, pos.y + 1, pos.z) + + if pos then + mt_add_node(pos,{type="node",name="walking_light:light"}) + end + + return true, "Done." + end, +}) + diff --git a/mods/player/walking_light/textures/walking_light.png b/mods/player/walking_light/textures/walking_light.png new file mode 100644 index 0000000000000000000000000000000000000000..bca3cf26e4198ffaee20b0cd9da9e3bef3b5bff4 GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blwj^(N7l!{JxM1({$v_d#0*}aI z1_o{+5N5n|x9$&6kiEpy*OmP~yC9pEYUu5rT%ZuIr;B3<$Mxg{AOLb%85rX}YgqwV N44$rjF6*2UngGl59ijjL literal 0 HcmV?d00001 diff --git a/mods/player/walking_light/textures/walking_light_debug.png b/mods/player/walking_light/textures/walking_light_debug.png new file mode 100644 index 0000000000000000000000000000000000000000..43e41bd4b77d915d804d9744ff958da9597c062a GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`>?NMQuIzU>IJv}B_eD?p2^8Wi z@Q5sCVBi)6VaEED_=!M4mUKs7M+SzC{oH>NS%Lg4PZ!6Kid#!3H*y_N;Be9X^*_E$ zr(@b~W8==IGv!&TMVU|MZs`vx==W!I^KqV?n99Au&wnP<9v=Z2rVEK|Yv(f?OpcA$ zDt1}FwDMf6v$(_0)vL}r**b(oN;*8R`l2;mNF~6SHO2nQR$KF4IYk#1nTtSM89ZJ6 KT-G@yGywofenX}J literal 0 HcmV?d00001 diff --git a/mods/player/walking_light/textures/walking_light_helmet_diamond.png b/mods/player/walking_light/textures/walking_light_helmet_diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..2649670f679014904ca9e9c36e3f3d6543d7564f GIT binary patch literal 524 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3-p)I`?e@QtJYILR^8g`SRtKt5;jDTW7U? zz4hkJw%fPc?$}|!cdz}veMZx#8_%3+GIy@&f(51v7n&_zY`%1<`Lbm|EfyWP`SI7UuYdmhSo?iF z(8XLOL4LtN8VZURNMtZDFfx0(IEF|_zCC!?smVZu;X&}M8~y24meM-{`2?&MbuPVp z@Bh(Pi?s7L#D1p*^}&hzge6#FFpF{nejt^(lx0`Do46I(v2Otea&LkGJW89H58+EzYY7|~H&zpX2##FDZTaK*>5zBs*f8_kJtG8FT*_}}JU7TT5 zC2=22?U5H2?=Tflz3la(IeXd#$1@%4^~%>dzL;E7!7Y1j^OQHS?;@P!H)rdVMC7HV xJvU!>C;P=>BWY)Lubxn`>`9Sa%?A@cJZBfol)31`ais(lGM=t}F6*2Ung9e&{`LR> literal 0 HcmV?d00001 diff --git a/mods/player/walking_light/textures/walking_light_helmet_diamond_preview.png b/mods/player/walking_light/textures/walking_light_helmet_diamond_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..33a273a2de0131b529240e4e89548ea1758d5f41 GIT binary patch literal 902 zcmeAS@N?(olHy`uVBq!ia0vp^4Gav73>?frmXCVhR3Jw!z$e5N$mMEg;Lc#+&SK!s zVc^bX;K^g)DPZ6!X5g)2;Hzcet7G76VBl+H;A>*wYi8hYVK6W-1Og)?BV!OSF*dd^ zH8nK@0dq5RD{~OAFkimh!otGR($Uh&)^hb~DWCJJDSf}Tbjm}qJCE*F|M_p9s6XfTQpH(8z0>x*pZ@I9y~ECzgoJn= z&(@2X>seK+J$Lt|=e+wF85ka%XPkbi{fpLK&-0hMzv#t!0-eiY_rR@c!n>u}FFmVD zmVO7SQuxteof#rEt!imu=9#JY*clvtGN{>v*)jZWeJr{FqJrUX^I>g=_nTMy3s-<>A=gz?GYePkt4cA#U%6MT;Cp`DZ1qatt%_Sau86bG$+1rT#?L>e zC^~E6-LpSgbKa$VPVT>YW%1sgs5yBB{1q7ipFk%4sN?y|WMk77&#xsK@F!;i!+v3i zWyF*J)Dw!bu5DVg^JhxZMa`LUgdB zr->17GF0W3?MFimL%m;L=vcM>wu$xG#(#R3Ex(Dxy*?2y*e$-!tV2VfmZ@*9Sz?R$ Q(_J7vp00i_>zopr0EPf4?*IS* literal 0 HcmV?d00001 diff --git a/mods/player/walking_light/textures/walking_light_inv_helmet_diamond.png b/mods/player/walking_light/textures/walking_light_inv_helmet_diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..07f5a0f1654d54cd68b1d04f0728329677b9daa8 GIT binary patch literal 371 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~JHN2Jh28OFQw9b`22U5q5R21GC)@fl8w#}U=WOJX z(#mtNVEiF4G02HK+`)^_!O_ak!AnCpSG1GK@gcW@Ziz`|fQvix(Zw5=PTg2O(P--P z=X)#V&N_5^{`2~jwfd#$z27tcFm9Mu6RY&X`=4CIteugUYPls8Ym>iC3M^-y6H##O zz@am-GJVI_PKsaeuARV|@T^byplpHFj5CZDQhb{q>{_LCQb%A;w9m0~ss&!3%;rW} z9q}tzx9oV^wfxC9uiAQFkPtbLey9InieGH#|KCmw%x_YY>N!>FXC5hU&`+@b!Jl@{ zYxateeKUVEmPzmYe(k4?oo)2P8F|IWRetstFx?H?<#uv@u8Y81@mD)5Sh9Y#asz{h N!PC{xWt~$(69A|cj;8e zzZI0>BE%I3ukD%=S)HU+#-zt4b zmby-q*-b6zwDHnM_k4M-)T%dIb3xx2axVh-$BX+A?retnBE7u)}{SE>zdf- zDd%NLc}`JzHgpa;L&huSi^jwCKBA#lEPA%5M*e|U^dzpls3;my4~$}U(6T&-EN@0? zg{T!eT@|8Mn1e>Gu$%9iP-^X=Vc6}4cBn@FLD&r?uEMA*8qrW{i8^RmA!>#Hc`eRT zfo(d%nSGLhEn+cPeWGV%0O^F}wPb67zt|D)|KUBQ?+bM7yFv;pWs8`-K60f#`!}&M zU!IKbtCG7b9uhNtJBp2An-w}TfJd-}ZaJ`{$gtwvD8=GvlQCaQ@-0@IHsv|$ZDQ6F zJV1z$Yi2paMo_dF+smkcWE|1&5j|X%_W}k|{o*oCGfWv8GR=}B*g3!y=fEp_{*7%R z&aw|-y!L90@mkFI`r3#wLNUWrdyLm&d*vfz{DvN_j4}RZWsLEuF~%Cb)eb3*o9Spn z%N{)>t);)(Y-n4fzj^?VV2cWI78q-_VQF+&k_1>Ikfl7%o4|Q+6m&)#(h6t5iunO5 z91}f`>BVJ-bULP|rJ)+XI5bqp4UK+a%8~gTtcJJ#dV)Jd_ewAZnXMQ1q5C&}rLEhb z`r>=udC5OL?_pGTnSa4^*kyk9$LcDA4)2=nr*EF$!G6s6y-fROjBAJAzQ(Izzz@7* zxG&hD{sVw*JQQ;bgv^hE`qFCrVraX=J#yYLuTzg7U=A>4$o-qZzazn*T@9xwm^ literal 0 HcmV?d00001 diff --git a/mods/player/walking_light/textures/walking_light_mesepick.png b/mods/player/walking_light/textures/walking_light_mesepick.png new file mode 100644 index 0000000000000000000000000000000000000000..9f98229997bd4b62fa816e9d54b79b79bb8cb1e0 GIT binary patch literal 402 zcmV;D0d4+?P)b_YUEk>d000SaNLh0L01m_e01m_fl`9S#00004XF*Lt006O%3;baP0003YNkly5=;+%+)2=xG8g07Vrx&FEo+6M*6wpFAN003uAUbq!@GF#rGn07*qoM6N<$g2UIEY5)KL literal 0 HcmV?d00001