From 23f69dfd1e8bac7469a00ecb6a1de5161f2475f8 Mon Sep 17 00:00:00 2001 From: iliekprogrammar Date: Sat, 20 Mar 2021 17:47:04 +0800 Subject: [PATCH 001/234] Core implementation of MC-like kelp drops. Highlights: * Kelp should no longer be able to survive without water (by decreasing its height) * When kelp is destroyed, each segment now drop a single kelp similar to MC. * Significantly refactor how kelp grows and dig. Possible optimizations might be included. --- mods/ITEMS/REDSTONE/mesecons_mvps/init.lua | 6 +- mods/ITEMS/mcl_ocean/kelp.lua | 270 +++++++++++++-------- 2 files changed, 169 insertions(+), 107 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua index 669edbcbba..8cd5ae872a 100644 --- a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua @@ -74,6 +74,7 @@ function mesecon.is_mvps_unsticky(node, pulldir, stack, stackid) end -- Functions to be called on mvps movement +-- See also the callback function mesecon.register_on_mvps_move(callback) mesecon.on_mvps_move[#mesecon.on_mvps_move+1] = callback end @@ -405,17 +406,20 @@ mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_brown") mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_light_blue") mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_pink") +-- Includes node heat when moving them mesecon.register_on_mvps_move(mesecon.move_hot_nodes) --- Check for falling after moving node mesecon.register_on_mvps_move(function(moved_nodes) for i = 1, #moved_nodes do local moved_node = moved_nodes[i] + -- Check for falling after moving node mesecon.on_placenode(moved_node.pos, moved_node.node) minetest.after(0, function() minetest.check_for_falling(moved_node.oldpos) minetest.check_for_falling(moved_node.pos) end) + + -- Callback for on_mvps_move stored in nodedef local node_def = minetest.registered_nodes[moved_node.node.name] if node_def and node_def.mesecon and node_def.mesecon.on_mvps_move then node_def.mesecon.on_mvps_move(moved_node.pos, moved_node.node, diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 2e0dfe1a51..9d6c092793 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -9,29 +9,67 @@ local surfaces = { { "gravel", "mcl_core:gravel", 1 }, } -local function get_kelp_top(pos, node) - local size = math.ceil(node.param2 / 16) - local pos_water = table.copy(pos) - pos_water.y = pos_water.y + size - return pos_water, minetest.get_node(pos_water) -end - -local function get_submerged(node_water) - local def_water = minetest.registered_nodes[node_water.name] - -- Submerged in water? - if minetest.get_item_group(node_water.name, "water") then - if def_water.liquidtype == "source" then +-- Is this water? +local function is_submerged(node, nodedef) + if minetest.get_item_group(node.name, "water") ~= 0 then + local liquidtype = nodedef.liquidtype + -- TODO: is it OK to optimize this to: + -- return nodedef.liquidtype + if liquidtype == "source" then return "source" - elseif def_water.liquidtype == "flowing" then + elseif liquidtype == "flowing" then return "flowing" + else + minetest.chat_send_all("its NOT OK to optimize into return nodedef.liquidtype :(") end end return false end +-- Is the water downward flowing? +-- (kelp can grow inside downward flowing water) +local function is_downward_flowing(pos, node, nodedef, is_above) + + result = (math.floor(node.param2 / 8) % 2) == 1 + if not (result or is_above) then + -- If not, also check node above (this is needed due a weird quirk in the definition of + -- "downwards flowing" liquids in Minetest) + local node_above = minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}) + local nodedef_above = minetest.registered_nodes[node_above.name] + result = is_submerged(node_above, nodedef_above) or is_downward_flowing(pos, node_above, nodedef_above, true) + end + return result +end + +local function get_kelp_height(param2) + return math.floor(param2 / 16) +end + +local function get_kelp_top(pos, node) + local size = math.ceil(node.param2 / 16) + local pos_top = table.copy(pos) + pos_top.y = pos_top.y + size + return pos_top, minetest.get_node(pos_top) +end + +-- Obtain position of the first kelp unsubmerged +local function get_kelp_unsubmerged(pos, node) + local x,y,z = pos.x, pos.y, pos.z + local height = get_kelp_height(node.param2) + for i=1,height do + local walk_pos = {x=x, y=y + i, z=z} + if minetest.get_item_group(minetest.get_node(walk_pos).name, "water") == 0 then + return walk_pos + end + end + return nil +end + local function grow_param2_step(param2, snap_into_grid) local old_param2 = param2 param2 = param2 + 16 + -- TODO: allow kelp to grow bypass this limit according to MC rules. + -- https://minecraft.gamepedia.com/Kelp if param2 > 240 then param2 = 240 end @@ -41,30 +79,6 @@ local function grow_param2_step(param2, snap_into_grid) return param2, param2 ~= old_param2 end -local function kelp_check_place(pos_above, node_above, def_above) - if minetest.get_item_group(node_above.name, "water") == 0 then - return false - end - local can_place = false - if (def_above.liquidtype == "source") then - can_place = true - elseif (def_above.liquidtype == "flowing") then - -- Check if bit 3 (downwards flowing) is set - can_place = (math.floor(node_above.param2 / 8) % 2) == 1 - if not can_place then - -- If not, also check node above (this is needed due a weird quirk in the definition of - -- "downwards flowing" liquids in Minetest) - local node_above_above = minetest.get_node({x=pos_above.x,y=pos_above.y+1,z=pos_above.z}) - local naa_def = minetest.registered_nodes[node_above_above.name] - can_place = naa_def.liquidtype == "source" - if not can_place then - can_place = (naa_def.liquidtype == "flowing") and ((math.floor(node_above_above.param2 / 8) % 2) == 1) - end - end - end - return can_place -end - local function kelp_on_place(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" or not placer then return itemstack @@ -74,8 +88,9 @@ local function kelp_on_place(itemstack, placer, pointed_thing) local pos_under = pointed_thing.under local pos_above = pointed_thing.above local node_under = minetest.get_node(pos_under) + local nu_name = node_under.name local node_above = minetest.get_node(pos_above) - local def_under = minetest.registered_nodes[node_under.name] + local def_under = minetest.registered_nodes[nu_name] local def_above = minetest.registered_nodes[node_above.name] if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then @@ -93,56 +108,56 @@ local function kelp_on_place(itemstack, placer, pointed_thing) return itemstack end - local grow_kelp = false - -- Select a kelp node when placed on surface node - if node_under.name == "mcl_core:dirt" then - node_under.name = "mcl_ocean:kelp_dirt" - elseif node_under.name == "mcl_core:sand" then - node_under.name = "mcl_ocean:kelp_sand" - elseif node_under.name == "mcl_core:redsand" then - node_under.name = "mcl_ocean:kelp_redsand" - elseif node_under.name == "mcl_core:gravel" then - node_under.name = "mcl_ocean:kelp_gravel" - elseif minetest.get_item_group(node_under.name, "kelp") == 1 then - -- Place kelp on kelp = grow kelp by 1 node length - node_under.param2, grow_kelp = grow_param2_step(node_under.param2) - if not grow_kelp then + local new_kelp = false + + -- When placed on kelp. + if minetest.get_item_group(nu_name, "kelp") == 1 then + node_under.param2, new_kelp = grow_param2_step(node_under.param2) + + -- Kelp must not reach the height limit. + -- Kelp must be placed on top of kelp to add kelp. + if not new_kelp or + pos_under.y >= pos_above.y or pos_under.x ~= pos_above.x or pos_under.z ~= pos_above.z then return itemstack end + + -- TODO: is this even possible??? + if pos_under.y < pos_above.y and (pos_under.x ~= pos_above.x or pos_under.z ~= pos_above.z) then + minetest.chat_send_all(dump2(pos_under, "pos_under")) --DEBUG + end + + -- New kelp top must also be submerged in water. + local pos_top, node_top = get_kelp_top(pos_under, node_under) + local def_top = minetest.registered_nodes[node_top.name] + if not (is_submerged(node_top, def_top) and is_downward_flowing(pos_top, node_top, def_top)) then + return itemstack + end + + -- When placed on surface. else - return itemstack + -- Surface must support kelp + for _,surface in pairs(surfaces) do + if nu_name == surface[2] then + node_under.name = "mcl_ocean:kelp_" ..surface[1] + new_kelp = true + end + end + + -- The surface must support kelp + -- Kelp must be placed on top of surface to add new kelp. + if not new_kelp or pos_under.y >= pos_above.y then + return itemstack + end + + -- New kelp must also be submerged in water. + if not (is_submerged(node_above, def_above) and is_downward_flowing(pos_above, node_above, def_above)) then + return itemstack + end + node_under.param2 = minetest.registered_items[nu_name].place_param2 or 16 end - local submerged = false - if grow_kelp then - -- Kelp placed on kelp ... - -- Kelp can be placed on top of another kelp to make it grow - if pos_under.y >= pos_above.y or pos_under.x ~= pos_above.x or pos_under.z ~= pos_above.z then - -- Placed on side or below node, abort - return itemstack - end - -- New kelp top must also be submerged in water - local top_pos, top_node = get_kelp_top(pos_under, node_under) - local top_def = minetest.registered_nodes[top_node.name] - submerged = kelp_check_place(top_pos, top_node, top_def) - if not submerged then - -- Not submerged in water, abort - return itemstack - end - else - -- New kelp placed ... - if pos_under.y >= pos_above.y then - -- Placed on side or below node, abort - return itemstack - end - -- Kelp can be placed inside a water source or water flowing downwards on top of a surface node - local can_place = kelp_check_place(pos_above, node_above, def_above) - if not can_place then - return itemstack - end - node_under.param2 = minetest.registered_items[node_under.name].place_param2 or 16 - end - -- Place or grow kelp - local def_node = minetest.registered_items[node_under.name] + + -- Play sound, set surface/kelp and take away an item + local def_node = minetest.registered_items[nu_name] if def_node.sounds then minetest.sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) end @@ -154,8 +169,36 @@ local function kelp_on_place(itemstack, placer, pointed_thing) return itemstack end -local get_kelp_height = function(param2) - return math.floor(param2 / 16) +local function kelp_drop(pos, height) + local x,y,z = pos.x,pos.y,pos.z + for i=1,height do + minetest.add_item({x=x, y=y+i, z=z}, "mcl_ocean:kelp") + end +end + +-- Dig kelp: +-- Each kelp from broken stem until the top drop a single item +-- Kelp's height decreases to the height below dig_pos +local function kelp_dig(dig_pos, pos, node, is_drop) + local param2 = node.param2 + local height = get_kelp_height(param2) + -- pos.y points to the surface, offset needed to point to the first kelp + local new_height = dig_pos.y - (pos.y+1) + + -- Digs the entire kelp: invoke after_dig_node to set_node + if new_height == 0 then + if is_drop then + kelp_drop(dig_pos, height) + end + minetest.set_node(pos, {name=minetest.registered_nodes[node.name].node_dig_prediction}) + + -- Digs the kelp beginning at a height + else + if is_drop then + kelp_drop(dig_pos, height - new_height) + end + minetest.set_node(pos, {name=node.name, param=node.param, param2=16*new_height}) + end end minetest.register_craftitem("mcl_ocean:kelp", { @@ -220,19 +263,16 @@ for s=1, #surfaces do sounds = sounds, node_dig_prediction = surfaces[s][2], after_dig_node = function(pos) - minetest.set_node(pos, {name=surfaces[s][2]}) + minetest.set_node(pos, {name=surface[s][2]}) end, + -- NOTE: whenever it becomes possible to fully implement kelp without the + -- plantlike_rooted limitation, please adapt the code accordingly. on_dig = function(pos, node, digger) - -- Drop kelp as item; item count depends on height - local dname = "" - if digger then - dname = digger:get_player_name() + local is_drop = true + if digger and minetest.is_creative_enabled(digger:get_player_name()) then + is_drop = false end - local creative = minetest.is_creative_enabled(dname) - if not creative then - minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, "mcl_ocean:kelp "..get_kelp_height(node.param2)) - end - minetest.node_dig(pos, node, digger) + kelp_dig(pos, pos, node, is_drop) end, drop = "", -- drops are handled in on_dig _mcl_falling_node_alternative = alt, @@ -314,28 +354,46 @@ minetest.register_craft({ minetest.register_abm({ label = "Kelp growth", nodenames = { "group:kelp" }, - interval = 45, - chance = 12, + -- interval = 45, + -- chance = 12, + interval = 1, + chance = 1, catch_up = false, action = function(pos, node, active_object_count, active_object_count_wider) local grown -- Grow kelp by 1 node length if it would grow inside water - node.param2, grown = grow_param2_step(node.param2, true) - local top, top_node = get_kelp_top(pos, node) - local submerged = get_submerged(top_node) - if grown then + node.param2, grow = grow_param2_step(node.param2, true) + local pos_top, node_top = get_kelp_top(pos, node) + local def_top = minetest.registered_nodes[node_top.name] + local submerged = is_submerged(node_top, def_top) + if grow then if submerged == "source" then -- Liquid source: Grow normally minetest.set_node(pos, node) - elseif submerged == "flowing" then + + elseif submerged == "flowing" and is_downward_flowing(pos_top, node_top, def_top) then -- Flowing liquid: Grow 1 step, but also turn the top node into a liquid source minetest.set_node(pos, node) - local def_liq = minetest.registered_nodes[top_node.name] - local alt_liq = def_liq and def_liq.liquid_alternative_source + local alt_liq = def_top.liquid_alternative_source if alt_liq then - minetest.set_node(top, {name=alt_liq}) + minetest.set_node(pos_top, {name=alt_liq}) end end end end, }) + +-- Break kelp not underwater. +minetest.register_abm({ + label = "Kelp drops", + nodenames = { "group:kelp" }, + interval = 0.25, + chance = 1, + catch_up = false, + action = function(pos, node) + local dig_pos = get_kelp_unsubmerged(pos, node) + if dig_pos then + kelp_dig(dig_pos, pos, node, true) + end + end +}) From ebf9f8c918f74255ae0f4adfc6440f7cd81cd9a0 Mon Sep 17 00:00:00 2001 From: iliekprogrammar Date: Sun, 21 Mar 2021 12:16:56 +0800 Subject: [PATCH 002/234] placing kelp now creates water sources, small refactoring. --- mods/ITEMS/mcl_ocean/kelp.lua | 118 +++++++++++++++------------------- 1 file changed, 52 insertions(+), 66 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 9d6c092793..4d5bf094c3 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -1,7 +1,9 @@ local S = minetest.get_translator("mcl_ocean") local mod_doc = minetest.get_modpath("doc") ~= nil +-- NOTE: whenever it becomes possible to fully implement kelp without the +-- plantlike_rooted limitation, please adapt the code accordingly. --- List of supported surfaces for seagrass and kelp +-- List of supported surfaces for seagrass and kelp. local surfaces = { { "dirt", "mcl_core:dirt" }, { "sand", "mcl_core:sand", 1 }, @@ -12,22 +14,13 @@ local surfaces = { -- Is this water? local function is_submerged(node, nodedef) if minetest.get_item_group(node.name, "water") ~= 0 then - local liquidtype = nodedef.liquidtype - -- TODO: is it OK to optimize this to: - -- return nodedef.liquidtype - if liquidtype == "source" then - return "source" - elseif liquidtype == "flowing" then - return "flowing" - else - minetest.chat_send_all("its NOT OK to optimize into return nodedef.liquidtype :(") - end + return nodedef.liquidtype -- Expected only "source" and "flowing" from water liquids end return false end -- Is the water downward flowing? --- (kelp can grow inside downward flowing water) +-- (kelp can grow/be placed inside downward flowing water) local function is_downward_flowing(pos, node, nodedef, is_above) result = (math.floor(node.param2 / 8) % 2) == 1 @@ -41,10 +34,12 @@ local function is_downward_flowing(pos, node, nodedef, is_above) return result end +-- Converts param2 to kelp height. local function get_kelp_height(param2) return math.floor(param2 / 16) end +-- Obtain pos and node of the top of kelp. local function get_kelp_top(pos, node) local size = math.ceil(node.param2 / 16) local pos_top = table.copy(pos) @@ -52,7 +47,7 @@ local function get_kelp_top(pos, node) return pos_top, minetest.get_node(pos_top) end --- Obtain position of the first kelp unsubmerged +-- Obtain position of the first kelp unsubmerged. local function get_kelp_unsubmerged(pos, node) local x,y,z = pos.x, pos.y, pos.z local height = get_kelp_height(node.param2) @@ -65,20 +60,32 @@ local function get_kelp_unsubmerged(pos, node) return nil end -local function grow_param2_step(param2, snap_into_grid) - local old_param2 = param2 - param2 = param2 + 16 +-- Obtain next param2 if grown +local function grow_param2_step(param2) -- TODO: allow kelp to grow bypass this limit according to MC rules. -- https://minecraft.gamepedia.com/Kelp + + local old_param2 = param2 + param2 = param2+16 - param2 % 16 if param2 > 240 then param2 = 240 end - if snap_into_grid and (param2 % 16 ~= 0) then - param2 = param2 - (param2 % 16) - end return param2, param2 ~= old_param2 end +local function kelp_place(pos, node, pos_top, def_top, is_downward_flowing) + -- Liquid source: Grow normally + minetest.set_node(pos, node) + + -- Flowing liquid: Grow 1 step, but also turn the top node into a liquid source + if is_downward_flowing then + local alt_liq = def_top.liquid_alternative_source + if alt_liq then + minetest.set_node(pos_top, {name=alt_liq}) + end + end +end + local function kelp_on_place(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" or not placer then return itemstack @@ -89,9 +96,7 @@ local function kelp_on_place(itemstack, placer, pointed_thing) local pos_above = pointed_thing.above local node_under = minetest.get_node(pos_under) local nu_name = node_under.name - local node_above = minetest.get_node(pos_above) local def_under = minetest.registered_nodes[nu_name] - local def_above = minetest.registered_nodes[node_above.name] if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then return def_under.on_rightclick(pos_under, node_under, @@ -109,59 +114,52 @@ local function kelp_on_place(itemstack, placer, pointed_thing) end local new_kelp = false + local is_downward_flowing = false + local pos_top, node_top, def_top -- When placed on kelp. if minetest.get_item_group(nu_name, "kelp") == 1 then node_under.param2, new_kelp = grow_param2_step(node_under.param2) - -- Kelp must not reach the height limit. - -- Kelp must be placed on top of kelp to add kelp. - if not new_kelp or - pos_under.y >= pos_above.y or pos_under.x ~= pos_above.x or pos_under.z ~= pos_above.z then - return itemstack - end - - -- TODO: is this even possible??? - if pos_under.y < pos_above.y and (pos_under.x ~= pos_above.x or pos_under.z ~= pos_above.z) then - minetest.chat_send_all(dump2(pos_under, "pos_under")) --DEBUG - end - - -- New kelp top must also be submerged in water. - local pos_top, node_top = get_kelp_top(pos_under, node_under) - local def_top = minetest.registered_nodes[node_top.name] - if not (is_submerged(node_top, def_top) and is_downward_flowing(pos_top, node_top, def_top)) then + -- Kelp must also be placed on top of kelp to add kelp. + if not new_kelp or pos_under.y >= pos_above.y then return itemstack end + pos_top, node_top = get_kelp_top(pos_under, node_under) + def_top = minetest.registered_nodes[node_top.name] -- When placed on surface. else - -- Surface must support kelp for _,surface in pairs(surfaces) do + -- Surface must support kelp if nu_name == surface[2] then node_under.name = "mcl_ocean:kelp_" ..surface[1] + node_under.param2 = minetest.registered_items[nu_name].place_param2 or 16 new_kelp = true end end - -- The surface must support kelp - -- Kelp must be placed on top of surface to add new kelp. + -- Kelp must also be placed on top of surface to add new kelp. if not new_kelp or pos_under.y >= pos_above.y then return itemstack end - - -- New kelp must also be submerged in water. - if not (is_submerged(node_above, def_above) and is_downward_flowing(pos_above, node_above, def_above)) then - return itemstack - end - node_under.param2 = minetest.registered_items[nu_name].place_param2 or 16 + pos_top = pos_above + node_top = minetest.get_node(pos_above) + def_top = minetest.registered_nodes[node_above.name] end - -- Play sound, set surface/kelp and take away an item + -- New kelp must also be submerged in water. + is_downward_flowing = is_downward_flowing(pos_top, node_top, def_top) + if not (is_submerged(node_top, def_top) and is_downward_flowing) then + return itemstack + end + + -- Play sound, place surface/kelp and take away an item local def_node = minetest.registered_items[nu_name] if def_node.sounds then minetest.sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) end - minetest.set_node(pos_under, node_under) + kelp_place(pos_under, node_under, pos_top, def_top, is_downward_flowing) if not minetest.is_creative_enabled(player_name) then itemstack:take_item() end @@ -169,6 +167,7 @@ local function kelp_on_place(itemstack, placer, pointed_thing) return itemstack end +-- From kelp at pos, drop kelp until reaching its height. local function kelp_drop(pos, height) local x,y,z = pos.x,pos.y,pos.z for i=1,height do @@ -265,8 +264,6 @@ for s=1, #surfaces do after_dig_node = function(pos) minetest.set_node(pos, {name=surface[s][2]}) end, - -- NOTE: whenever it becomes possible to fully implement kelp without the - -- plantlike_rooted limitation, please adapt the code accordingly. on_dig = function(pos, node, digger) local is_drop = true if digger and minetest.is_creative_enabled(digger:get_player_name()) then @@ -360,25 +357,14 @@ minetest.register_abm({ chance = 1, catch_up = false, action = function(pos, node, active_object_count, active_object_count_wider) - local grown + local grow -- Grow kelp by 1 node length if it would grow inside water - node.param2, grow = grow_param2_step(node.param2, true) + node.param2, grow = grow_param2_step(node.param2) local pos_top, node_top = get_kelp_top(pos, node) local def_top = minetest.registered_nodes[node_top.name] - local submerged = is_submerged(node_top, def_top) - if grow then - if submerged == "source" then - -- Liquid source: Grow normally - minetest.set_node(pos, node) - - elseif submerged == "flowing" and is_downward_flowing(pos_top, node_top, def_top) then - -- Flowing liquid: Grow 1 step, but also turn the top node into a liquid source - minetest.set_node(pos, node) - local alt_liq = def_top.liquid_alternative_source - if alt_liq then - minetest.set_node(pos_top, {name=alt_liq}) - end - end + if grow and is_submerged(node_top, def_top) then + kelp_place(pos, node, pos_top, def_top, + is_downward_flowing(pos_top, node_top, def_top)) end end, }) From ca635b69be351a8cd8dfcaafa2536f659932e6c9 Mon Sep 17 00:00:00 2001 From: iliekprogrammar Date: Sun, 21 Mar 2021 14:06:54 +0800 Subject: [PATCH 003/234] Various fixes. --- mods/ITEMS/mcl_ocean/kelp.lua | 39 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 4d5bf094c3..73b2aaeb42 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -2,6 +2,8 @@ local S = minetest.get_translator("mcl_ocean") local mod_doc = minetest.get_modpath("doc") ~= nil -- NOTE: whenever it becomes possible to fully implement kelp without the -- plantlike_rooted limitation, please adapt the code accordingly. +-- TODO: In MC, you can't actually destroy kelp by bucket'ing water in the middle. +-- However, because of the plantlike_rooted hack, we'll just allow it for now. -- List of supported surfaces for seagrass and kelp. local surfaces = { @@ -25,11 +27,13 @@ local function is_downward_flowing(pos, node, nodedef, is_above) result = (math.floor(node.param2 / 8) % 2) == 1 if not (result or is_above) then - -- If not, also check node above (this is needed due a weird quirk in the definition of - -- "downwards flowing" liquids in Minetest) + -- If not, also check node above + -- (this is needed due a weird quirk in the definition of "downwards flowing" + -- liquids in Minetest) local node_above = minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}) local nodedef_above = minetest.registered_nodes[node_above.name] - result = is_submerged(node_above, nodedef_above) or is_downward_flowing(pos, node_above, nodedef_above, true) + result = is_submerged(node_above, nodedef_above) + or is_downward_flowing(pos, node_above, nodedef_above, true) end return result end @@ -114,7 +118,7 @@ local function kelp_on_place(itemstack, placer, pointed_thing) end local new_kelp = false - local is_downward_flowing = false + local downward_flowing = false local pos_top, node_top, def_top -- When placed on kelp. @@ -136,6 +140,7 @@ local function kelp_on_place(itemstack, placer, pointed_thing) node_under.name = "mcl_ocean:kelp_" ..surface[1] node_under.param2 = minetest.registered_items[nu_name].place_param2 or 16 new_kelp = true + break end end @@ -143,14 +148,15 @@ local function kelp_on_place(itemstack, placer, pointed_thing) if not new_kelp or pos_under.y >= pos_above.y then return itemstack end + pos_top = pos_above node_top = minetest.get_node(pos_above) - def_top = minetest.registered_nodes[node_above.name] + def_top = minetest.registered_nodes[node_top.name] end -- New kelp must also be submerged in water. - is_downward_flowing = is_downward_flowing(pos_top, node_top, def_top) - if not (is_submerged(node_top, def_top) and is_downward_flowing) then + downward_flowing = is_downward_flowing(pos_top, node_top, def_top) + if not (is_submerged(node_top, def_top) or downward_flowing) then return itemstack end @@ -159,7 +165,7 @@ local function kelp_on_place(itemstack, placer, pointed_thing) if def_node.sounds then minetest.sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) end - kelp_place(pos_under, node_under, pos_top, def_top, is_downward_flowing) + kelp_place(pos_under, node_under, pos_top, def_top, downward_flowing) if not minetest.is_creative_enabled(player_name) then itemstack:take_item() end @@ -175,26 +181,24 @@ local function kelp_drop(pos, height) end end --- Dig kelp: --- Each kelp from broken stem until the top drop a single item --- Kelp's height decreases to the height below dig_pos local function kelp_dig(dig_pos, pos, node, is_drop) local param2 = node.param2 - local height = get_kelp_height(param2) -- pos.y points to the surface, offset needed to point to the first kelp local new_height = dig_pos.y - (pos.y+1) -- Digs the entire kelp: invoke after_dig_node to set_node - if new_height == 0 then + if new_height <= 0 then if is_drop then - kelp_drop(dig_pos, height) + kelp_drop(dig_pos, get_kelp_height(param2)) end - minetest.set_node(pos, {name=minetest.registered_nodes[node.name].node_dig_prediction}) + minetest.set_node(pos, { + name=minetest.registered_nodes[node.name].node_dig_prediction, + param=node.param, param2=0 }) -- Digs the kelp beginning at a height else if is_drop then - kelp_drop(dig_pos, height - new_height) + kelp_drop(dig_pos, get_kelp_height(param2) - new_height) end minetest.set_node(pos, {name=node.name, param=node.param, param2=16*new_height}) end @@ -264,7 +268,10 @@ for s=1, #surfaces do after_dig_node = function(pos) minetest.set_node(pos, {name=surface[s][2]}) end, + -- TODO: add ability to detect whether the kelp or the surface is dug. + -- Currently, digging the surface gives sand, which isn't ideal. on_dig = function(pos, node, digger) + minetest.chat_send_all("mo2") local is_drop = true if digger and minetest.is_creative_enabled(digger:get_player_name()) then is_drop = false From fe937665f93d027f4daf7f6b0fc45629ed5f466b Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 24 Mar 2021 08:27:31 +0100 Subject: [PATCH 004/234] Fix #1336 --- mods/ENTITIES/mcl_burning/api.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_burning/api.lua b/mods/ENTITIES/mcl_burning/api.lua index 4eac333a26..b08a0fb707 100644 --- a/mods/ENTITIES/mcl_burning/api.lua +++ b/mods/ENTITIES/mcl_burning/api.lua @@ -167,7 +167,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason) hud_elem_type = "image", position = {x = 0.5, y = 0.5}, scale = {x = -100, y = -100}, - text = "mcl_burning_hud_flame_animated.png", + text = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. 1, z_index = 1000, }) + 1 end From a47eda44e98627cab07f4ee69a043e45fbb0b388 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 24 Mar 2021 08:54:23 +0100 Subject: [PATCH 005/234] Slimes can burn --- mods/ENTITIES/mobs_mc/slime+magma_cube.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index 54269b46e6..7c21fb8124 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -109,7 +109,6 @@ local slime_big = { fear_height = 0, spawn_small_alternative = "mobs_mc:slime_small", on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5), - fire_resistant = true, use_texture_alpha = true, } mobs:register_mob("mobs_mc:slime_big", slime_big) From 43a60e0c57204b71fe0a2ee6ca00bcfe8635c9b6 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 24 Mar 2021 09:00:31 +0100 Subject: [PATCH 006/234] Fix #1357 --- mods/ITEMS/mcl_enchanting/engine.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index 83149862af..ce6e3543a9 100644 --- a/mods/ITEMS/mcl_enchanting/engine.lua +++ b/mods/ITEMS/mcl_enchanting/engine.lua @@ -582,7 +582,12 @@ function mcl_enchanting.allow_inventory_action(player, action, inventory, invent local listname = inventory_info.to_list local stack = inventory:get_stack(inventory_info.from_list, inventory_info.from_index) if stack:get_name() == "mcl_dye:blue" and listname ~= "enchanting_item" then - return math.min(inventory:get_stack("enchanting_lapis", 1):get_free_space(), stack:get_count()) + local count = stack:get_count() + local old_stack = inventory:get_stack("enchanting_lapis", 1) + if old_stack:get_name() ~= "" then + count = math.min(count, old_stack:get_free_space()) + end + return count elseif inventory:get_stack("enchanting_item", 1):get_count() == 0 and listname ~= "enchanting_lapis" then return 1 else From 46c632843237165ada8453d5c076fe1278c530c9 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 25 Mar 2021 09:24:38 +0100 Subject: [PATCH 007/234] Something secret :P --- mods/ENTITIES/mcl_mobs/api.lua | 31 ++++++++++++++++++++++- mods/ENTITIES/mobs_mc/sheep.lua | 44 +++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index f8881d7416..f1df87e8b7 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -283,6 +283,33 @@ local get_velocity = function(self) return 0 end +local function update_roll(self) + local is_Fleckenstein = self.nametag == "Fleckenstein" + local was_Fleckenstein = false + + local rot = self.object:get_rotation() + rot.z = is_Fleckenstein and pi or 0 + self.object:set_rotation(rot) + + local cbox = table.copy(self.collisionbox) + local acbox = self.object:get_properties().collisionbox + + if math.abs(cbox[2] - acbox[2]) > 0.1 then + was_Fleckenstein = true + end + + if is_Fleckenstein ~= was_Fleckenstein then + local pos = self.object:get_pos() + pos.y = pos.y + (acbox[2] + acbox[5]) + self.object:set_pos(pos) + end + + if is_Fleckenstein then + cbox[2], cbox[5] = -cbox[5], -cbox[2] + end + + self.object:set_properties({collisionbox = cbox}) +end -- set and return valid yaw local set_yaw = function(self, yaw, delay, dtime) @@ -298,6 +325,7 @@ local set_yaw = function(self, yaw, delay, dtime) yaw = yaw + (math.random() * 2 - 1) * 5 * dtime end self.object:set_yaw(yaw) + update_roll(self) return yaw end @@ -645,9 +673,9 @@ local update_tag = function(self) nametag = tag, }) + update_roll(self) end - -- drop items local item_drop = function(self, cooked, looting_level) @@ -3487,6 +3515,7 @@ local mob_step = function(self, dtime) yaw = yaw + (math.random() * 2 - 1) * 5 * dtime end self.object:set_yaw(yaw) + update_roll(self) end -- end rotation diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 681c68e1b4..84650b4ddd 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -25,6 +25,19 @@ local colors = { unicolor_black = { mobs_mc.items.wool_black, "#000000D0" }, } +local rainbow_colors = { + "unicolor_light_red", + "unicolor_red", + "unicolor_orange", + "unicolor_yellow", + "unicolor_green", + "unicolor_dark_green", + "unicolor_light_blue", + "unicolor_blue", + "unicolor_violet", + "unicolor_red_violet" +} + if minetest.get_modpath("mcl_wool") ~= nil then colors["unicolor_light_blue"] = { mobs_mc.items.wool_light_blue, "#5050FFD0" } end @@ -112,7 +125,7 @@ mobs:register_mob("mobs_mc:sheep", { end, -- Set random color on spawn - do_custom = function(self) + do_custom = function(self, dtime) if not self.initial_color_set then local r = math.random(0,100000) local textures @@ -149,8 +162,35 @@ mobs:register_mob("mobs_mc:sheep", { } self.initial_color_set = true end + + local is_kay27 = self.nametag == "kay27" + + if self.color_change_timer then + local old_color = self.color + if is_kay27 then + self.color_change_timer = self.color_change_timer - dtime + if self.color_change_timer < 0 then + self.color_change_timer = 0.5 + self.color_index = (self.color_index + 1) % #rainbow_colors + self.color = rainbow_colors[self.color_index + 1] + end + else + self.color_change_timer = nil + self.color_index = nil + self.color = self.initial_color + end + + if old_color ~= self.color then + self.base_texture = sheep_texture(self.color) + self.object:set_properties({textures = self.base_texture}) + end + elseif is_kay27 then + self.initial_color = self.color + self.color_change_timer = 0 + self.color_index = -1 + end end, - + on_rightclick = function(self, clicker) local item = clicker:get_wielded_item() From dbc6dd8cb3c8bc2c3e0fdf1b5c9b12a71227e224 Mon Sep 17 00:00:00 2001 From: epCode Date: Thu, 25 Mar 2021 08:52:32 -0700 Subject: [PATCH 008/234] Add villager sounds --- .../mobs_mc/sounds/mobs_mc_villager.1.ogg | Bin 0 -> 14734 bytes .../mobs_mc/sounds/mobs_mc_villager.2.ogg | Bin 0 -> 14564 bytes .../mobs_mc/sounds/mobs_mc_villager.3.ogg | Bin 0 -> 14773 bytes .../mobs_mc/sounds/mobs_mc_villager.4.ogg | Bin 0 -> 10341 bytes .../mobs_mc/sounds/mobs_mc_villager.5.ogg | Bin 0 -> 14731 bytes .../mobs_mc/sounds/mobs_mc_villager.6.ogg | Bin 0 -> 11187 bytes .../mobs_mc/sounds/mobs_mc_villager.7.ogg | Bin 0 -> 11068 bytes mods/ENTITIES/mobs_mc/villager.lua | 4 ++++ 8 files changed, 4 insertions(+) create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.1.ogg create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.2.ogg create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.3.ogg create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.4.ogg create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.5.ogg create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.6.ogg create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.7.ogg diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.1.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9c56b0f65bc367e060329fee2843eb9ccc5c9753 GIT binary patch literal 14734 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 Fe*pY9T<8D* literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.2.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..bafc77b7eab6f58d17dbd56ddc2f4c1da53d86db GIT binary patch literal 14564 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 ZUU0tu;-eYfb3&=*j_1BOjmEXW{|EX3(7*ry literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.4.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.4.ogg new file mode 100644 index 0000000000000000000000000000000000000000..5c9ee492ba4d2315ab820b8149dcb5b73cfc62f6 GIT binary patch literal 10341 zcmeHscUaR&x9}to2z3)oVhE@qfItXJBp_f5B}i2gNDPT3gdzcKAa>nIGlU`_vh;<} zLI9U2SXZS5J4!WT0ekQ3ik15dxclz+e)qZed!GAz|J`|pVdk7ObAEH$oS7_NyEX*C z!H;5{d043F-mr}Ehs}g-*^nRw1Boi}wOlp;C;$XjcE$&y{p@NBs%*Cx75Hj;D#whXf(#WtB8%GdS3{&lVgb+w zVq3kO>PLRDy>4sqHaQ8EZlYzb^+a7MbIeVz^TX_j^>wXvaqD~StdT}x2x#Mg?rV{T zVQCtn#3CIJHT%pH&Rf)%CFqmomC5?^&J$At=RK`Cu+06bygJAInQiMePXmY6e*Zw~ z5GUf$X`NNO5_{bqm;Gq;Cig*vzQt3=G!o^B)GRNtt1C)?mYUiY5s0B}f~9#FKPBdp z()>!F)$(@~<}~L%Cq_tU5F085hb#m)O7^t*#E4*(fBN1fx++s>1OW>1%X%o2>j_UC1}(R0G(>C+GKtKk_O9RAi;S>;-c$`LDwNs zXe9Dqm%Wqr0&T>iJi0JejC9HkpA?H2S{7f0^fH{{1QAH89uP~emAt>=W?b^HvH?>% z(2)^ZYICBYsB}_;@x7+^Azj*CELK$(Un@!M^)oD~o$75jDb;Om=!amYkIRgEOv52M zQGbbU!woJpH|$!;Bl!so)XOL+wP`yMIGZ+xJVdfu*PW_FH`e?v+z%haZJbMoZQ zi2$UcCaw6dX3~_Wthgp$O1@}&X{NQJDJ;tW}FcH5(h#6xbr zakXv3Jp0-LmcL!?lt)2IB}V3Y=$KAANqSMjMZ0>)EB>jtH&$2CGy48fuf8>Bnpi`% zZ=OSl(;{{#d&QP@VZS8ZJeIafoiuuV_vrQPHPh4o-LU@l8~`~@>ZDH=2(zf?%2Jkj z>P;#5FVES8IhSXCAXT) z5_RKf6#v-nu%ka5X3A|wuP6P(b2KhOa?82zo3H&Z&#AP{x#yZ=>6dR6mOp!Y;o6Ln zhT@8+4Kn?I^PCuIeUY?YB7H2$vCSwHWt1pR$l@;^dVcc1t$%yY(gZ80LY~7&u=P#G{tWK1YuxTrfE(OsI>Rd z=+hR_r!l66|FafiL}O}0^~W+0qrOmBAMFP(h)cT@gHD4^lK*-6Pk1q%Vaxx)i%tuo zhX(!6IsNYn|0{w2RsxWT!;GOnoM)AVJzVSx1N-jN^ND_MXyS;lHw(8B0;i2}aSMMc z(H;29JD>yh9c|mpg+JBl<`a3fO#O)BG0wVU+ARc%8W!KP$ya}9Er`MMn z3tu>pD(a+#EB^D369XWI=>jpBc9H(~H&y$Z0N|P*83yGSzWGrwAdU*F&;=krYWvLp ze3}1u=)W<9iERPcC*$HanqPwFM1;}vDF%Wt5Tvz@K*zu|#Bj~mnbE9qy0)}PYk)$4 zv5lBZ{WRtS*TPzn?EEH5z<_sN6qE#IkZ4dBUGaE(o!-^=(7tV@G7%g)ULdg}G-7v& z@uwIE$DH>EL@UsK*R}BBcA2dd%AXV$H&HIV_hw>(LfET*xz8pdfu~%I`7$p`#^G+V3XoXIVO)C|OXD1KYUjk49b>m=En9i7HbQns}$J$|l z*p76+AU}*W3p)M=U>0ZYVBU;Xitt^#6Hl`PcpB|7TCl zi)(J<0DNzn7CkIA+o{Q_9Gjyvop9I$AoU=vdq}8HtP1k|{jr`|ZnoA33whFJPYD%S zTQkUur{b=<=~mSg@T7J}??DQJV9-{0D-A4a3wW6hNAacc7LeBBAXtQxe;WjYwh~A2 zKLNp%Dtufv!?u*K!NxT^+dWJSP!91Tn%ZVpXXR^PO>M)Z0@l19ObFB~NpvKZ zKIR=T=^URK;s6oHLAGESncdLCgA7M6Dl6Mzs35Ty0qBcd0o@w!VPne1g;(oMpDCVH z%n9fY37KAx#=_F^TYpuB;eOy(vUN zK15gh0|7CD*8hQk7(vTS&44~7n z4)oBb7IsuO5A-B@0T>6smnD`+Vjj7=FI-Ib^!D-f4_p=ug*VvbNk|7UBy#G)sTm`Y zQ!gF##gp@a=A}b(ES81EzcpL<`rCx@gxLgcf&jH<6DAXO6R-)b?;l^kGsiv+x&Lk< zxnX-nHEDP3%8I4d&Q}wOba+G-%ogVBuP-&RNPl?ehy!7Ul(_qI_xCklzpE(S_eHx` z075iv(}@T|8Igi?Dmi|OYP1Z6+vOeBz#p_#43$W-V#|X$evv-$b`9n@B+8(Mgi91e zLq!LAUQzlO3bWDnICP^BIOF1s;_!tyb>(cFA~rTSX(UG5qYZ)17AKQjI;UOz^^BsD zEGJY`Wh76ok%RxaaJ0cTo*{zS)hfKw5-k$1+3dC#mL9RwAC&k<3z8TL2~lRr(K<@u?`q4ayyW}$IH$N2f4c_#jAd~6;Or)TYtr&w0C zZdhhhVIT?7t8rA~4J1@2C&-q>*}?-?>VohtVaJj!T;vW-VO%a3&xyCFV`I&lOof%4 z_y%E7VO<(2*;dN6)aNi8>qK%kwzMfjT%g#n_tRis-Re=gBOvSa0b$%abVssUjv(Vn zYH=;Wan|?ct>4z2O-q9*8BFb)?&Y6x?ROFyHkXl(oN|IQu#b?%oL#D}>F%oEh^OR!BUtW=(}*7i*5SB?teL z=-ZzsyO-ZH*pJBCo2GZiIrKdG&ZoP_&W2N?eGVT>KfK*9Kow)5|OGC#|aAXYLcfJahi&U4dZl# z$yLeNK5`7kUMlqNKK=VjhoB)IpaT?>mQ3QdDN52#8_+EUDO~XC3kT^DI_jH$C+*zu z{BQFOa(@f0{k@?|N|Z6_2!Wj_g(lk&NR3Bz_iKluX22yx;n3Kq*i>7r5H-}XpAS2z zI^|)#serz)SrW4usRrp-Wxj-+?I6c7(C9u3T(-=Xgueh_Fukh@^%F+V`DPixr;EQ_ zzrRNI7-rIh0Lx$t!5!z;0y6T&&gQpg$L~fs?z*}ENL-8^8>RlpyZ`gsu5*I%qq82v zcAWnHDu-o`?%CyDV`ACgU<|jrY$vpWg%e@G(IHm3BJ;FeY{Xj2I(FmH7RPuKY*#A{ zt*nJU*}GY2A(T`pi0NE`rR>(X9Z$cV#yd)Mw6!Tjd5=P7VVPMmzoGsCS@@jBt5zsT zg1hl>l7fT9rjW@5`{CdaG)CK_1E`7I6h>Pc+=XbVn>{)bm(j#+kt}0-Xa(O{ijky# z)d2+6Z-c??#&ntR3QowAsd;?pHBtPz{&Tw3UD#0pHiDmt%@$(KVBX%}Cqf12OV0+^ zGZ&ao;%UQLzizdO5*{{LCRtW^=PTEWX7li0Of4^7&MflvEkQ*eoH-JkVxMU~QKO;K{gj(UELL z<=UI4dty+i_zo8tw;t!=43|qt?!gGdL}oP0#+mr?7)%?@*w;)pdHQisxvtB?H!K~m zlnCP-c+CelB=Q1Q=%i-jg+o$&C2pA7WO{6QR2K%fD=N zoTq<{Z_c`L_uH#yck6e%;!P1xW{AJ9cB3l_it}Uj1988EK(1pVfSG6q!hxVoDkdnl zAnO{qftf{h87g|SP7yxcximi9z^tXU?_@SfMvfIH1%!YhZfIi+<*1jlU|R5Ii6Yj! z178QH=}VLj$;KXtR-v~CiqF_A1ll$5cB!)zVX6P^n;%53rJ7C_GtaC)^=;T0N+pd&{f zYl9gQMz_9%qf{i@lIe#-t0{pC;=6g7v8bwJG*Eu%wWXLr_m0!HhMA`)`u+Uy6Zq~L z*%o~|_w%JM9|Q8TtrXk$dvW514I0k={_|PP4PRNw)`6KfbVmLxgVj(rS{3>SwxbuA zY=yz<7i=V(Xuk*rz}rx%92tpFhjkBgP^b`Wydi&QrmE%Ge4{~a3NAC-$fr*dOO;o4 z$YffAvZ4Kc61=G2j+8$~mC>{fXUJA$}abfTKn! z54T?rdHdx}-dEn_PZ*0u1se~A>Akf+vwGX_2YmD%mmEZ`x%WKn+)j^1)d{RPrKlRw zz(UsxWr!OG?w#+OJ$rT!Q2yN{YaZ|h!5pj0~G;v!4wCycJn+F>mwyVK(sLvVe(|KXZj zxC*#cqS%_hPiUk7IFKHmLD?6xSzn4kH;O|5hTFtoGZ2Wrz0O))WT^$7RF@<1g``nE?$hyi#Or1pjs|v$2End_~hN}wb-@fXr&<2NOpohH}Sw>omsiY z6Sc+|G^4e0M1i$>A7l@cEZkSzuqDhhfX47>6|Q( zED)zT1Z6CqC+d9Qh*rv_aGd=xLAx0n+N6J;+MYbBH+cE_X%LEG2J+>CY!VNW48`Nt z(wD(mG1v}ndoE(#gC&;2EB#V=GNG>J>B3)Hu7{zp3@sU!A-<`L^?tlKnHky)*XL!X zJSYc_tQF}-%YpHjH2`})Mc#4}x!;{X>(U0rk)nx*2R2=;d73)9i*mN1SNMIdM8=vg zA(-;X^$R4muC56JSf_6w#YNQ(;JT1wfw*S2GdD#VuA2QEC*=uMll87sfurs9LMqZ3i29;?woE(tgvI)8M)9$pwq&XAhc0KN9 zIZ4Oxwb1MqKYhsDeV8r;XPE$3`-fSLB;5M=e2H+=7 zT`>Twx2KLRSm^QDddZ%KW$*&>e$=jgHoj*coSQr3C+@$}dc;T#S;#{=KEw^Rz%eg1 zPmlE{W|J;bq6b-sSYV@Wz$0-x`CTm`&Vg-grIUk8iA%AZXFKfRFxao)c+|%@D->KM zx+A73hJjWRk=y2KW3#F5hBEH@cb`0Ys}feP2pPwGWv_nfuH8Wx;x+3i$MSjanIr5o z2Vt{7?;qnuH($P<`^VkX-~G)O(+mh(+V%Du>B|K}C`V-vLc9IYpMUC|eBLwgnpjy$ zl}e=YT){<$IF?w3>K4FA6)wgXtX%f)maf4z?5UvEh1P9CZhTE_O2nt7AeX zqtu`8SKsX_n`0gQ0Y|{z+j@C)JZ9XnJ|H9P^aeT0`*yOgNq-?(mB%IP!gO(hN0_C; zRJ68sARc-%>#me^NS%cnNVtLaSP74UYfLgQV;gq2(uPiA?bD4zF+&2QWSM@9v)IR; zl-`y4e21#C(xWW~t&G^*)%o=>JieOgpb&VVjIfAq4o&XP?&dYeY^2thjs@->oC#00 zpQX>~#%B+cY4wDq{Ezz$lAq20O1M990V&K(cHn5Q>veF+IBz-fjIt~L%!$|VcS$n% zFi`00JCvbv^VTTE3PH0EyS;4>92{@U)s_b) z4b#GIYEed4KL}6Vupmb-b;a_M-CMIwTwdQl@QY5oaAycM6R+fA%B82{#OjWNLCrIC zK;5Y}beO=T-5q>A&VO-ElmUVPSR7+@cLSpA!7uqM)@H8N$+r61EI#m+_3l~x+so@d z1m+p#uAGsmo%tFV|I z%i}SX(H1&|3Tc|e83QSl(S$a$r1Duiq2x(L8kVxV>m$qi_*)}yuRn8j#tPJanE-~eqF-OZ3g1}ke z%m`{x)~W@TI7zLMP#UD}mqOP8wl^id)o)0;*Oo{1X_6?2@-#aE_Xx&IJJq6TI=iny zE3Q=|g$#)O!0xlGyp`v;B(EMii>em%YUG<}} zk-LwcEM8kPJ~Od!yg#?Pt1R!{&dXu<0=#mJzqr8~%*|QmtfCp+Ma3D##l_G(JZ{hj zC8zr_|5af={Y2tB&YhJ0AS z2&Rguu@3Rzxh$65EU3n|tv4_;3>kFnkT#?vX2*t$)U2R3ZD;hgDq#xZ=BUfMw!`oH zvlXxBb_?nDwm9t2S1d7u9TAbO;I)6|^+xfT@01*Z{fqNar%081SX!B4vUD9o8MFDr z(28TU)_3DEHRirn_W~w%_-}h7P_@q7zi-9xr(L{*rT(kkvTrgI_o$<8-AQ2%YuS@cUv{Nj~QI$n*9 z<&xSPiny2e78Ms27ekN0fXrE7$mh2m6BH>pL$fKWPK8JvsVb?><~Rg(MTZ&%8U(gU z1?m`iQISre>_gF)Z6{iPt1RC=@~r&#m=%M^#|aj>=HlnSsez9!5?T8F=JK6Pz(zDn z)U($-x?R$hf%XRAntp%QlbtOm&J*(cj_?Lga^5TZ@xnV<0YucfDz#PJH-nG<=>wPc zKSnPdSnx-WC_C~t@H}3!3jbMDzWFZc4M}J2oBpe+J#?74D_9*pn6STL_6I_2)n)m^ znIS>XoCiD8{Nj!68dz?Q%Ayo4CryElA3Cm>&e_@(M1PrasxJF1> z2}?8|BZ)j`eZF-5XTP~svtkJ~eidl#zNgjiEwjd_#jIYuHdC6Lvoh%-{LR9s@&g}_ zZ5Uk_mT+g{d;If_^p~<-C%$%m^4Zdl{cYaQ=K~#yzg)^X6O)(p^|MtBTpOH;8jQ~v zy0>{t)rc0~=Sm^hVcFX0ibXB2jg5^P%+U*6Q42JWWlm0102~7YwD?lz0jX#RUK-dG z&gC7u(c0Iq6R(#(5~J#8HQAClq2A4W3APb;)KS?I9QvlBu|~qG>5NKMc&HLvv}UhN zs$J=R?jRZ)TK(*rK$ZH04C~c};k6q{3T~6?WQ(m?s_mY3yNF#ym*0~thTh?5H=FL9 z*s%D{?9yAUg(=<_+RZloR{ZBO(@p0xzO^mKeOPgA$HzXCYpa4?_qLMphwkslT_Rc4 z>N-aIh|tZ&h)uxE=y=&uN!?1TZC01n-uqEOCw$+WkFtVd6^o^ZTHxwx5;0rjdPK-D z)!Y{j>9BNFvK)^~myC3FwqoMy*nFO{HjOJSDdec&0d4L5n1Pewx9JFMmv$(#RcHwa zmi-Us7(e|mf!rB3gCs#@N)QfBb;fLOW;53NS``Dir1Uwz$^FF?Gt4=>M5!n^B zH6uqt^h!qAe-d)$Ec`i7JN{+I7eqTe37!LA9KG<*5B{BbeolkW>}qmM_wPQPzcI4k zux*Ea!}LFruUM!&AP2mGc7jo-IXY>AFILHGIY!{{yIR$}BDhd=;ED^kO=yR68R_(~ zSESoXMBzhHw!OQvLZV<|Efq3yZDPfPn`IUW#SS=og%6to5`JA`5IA<~)Tu@`Y1;Q! z?hSMJ#~zivXG1^6^`2RO>BHh_q{laJ_OH41I1p@g+Ilp$@beJw>;gt36MDenK3+Zh z+Skuzdath*zp-vAr#~p$aH%=>#0~b*^{21?`YC_A!4dYS%NOF4T;?BJAC>r=V^ewp F{0E)bG4}uf literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.5.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.5.ogg new file mode 100644 index 0000000000000000000000000000000000000000..acb236445e2b530640a1c98a54c81d20a9a3672a GIT binary patch literal 14731 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 literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.6.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.6.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1ef7a522744a727da6082e2a3a1f2bf36fc77604 GIT binary patch literal 11187 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 literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.7.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.7.ogg new file mode 100644 index 0000000000000000000000000000000000000000..c2743fbcc640651eedc1529bbed4e3c209552fc1 GIT binary patch literal 11068 zcmeHtcT|%}+xLVTstF_^AYkYr1|>jPKy*V1hAIgJLjWbANVOrX-B1kyEP#j<7eWyt zQ6dBtcNLHzh#*K2u`D($h-=wZS=)OD+X=Do%5XUzjw|s%v^KLT=!gM<~IXt zHf#t23gBBhA9tB1uO>}S&%lgfX`8lk<5T1W1P4u6zgqWS6q$XQCdus*JQT2rNy~2Y*ap}=g$J? z5RC>v3Gnc02WqCh69%0(V66^pt#XbJa5{lg70{=g)w+JSjM`Y=TA#Ra(Aom76{-v^ z98hQ`*(ip*;POp!uu!qzaBHv0iHfc2godgNb-P|%rk~xj+M)oLXALz6T%O}whuk%6 zT5tIHk;X!zPW`MBu{&kZ`ANmMLT!E>IOtp4RrI3~?r{0^eCztstX#S}44bccL!|4HhwZ6B!TwArrADkxi@BMWdNXZLXlZuXxjmuhvco2_Bi?6o zusPrIhdsZ%m*@GV<6xl5%(>*Dwb0Z+_`q4Hn3dC{0HWn8!KoFRS{K%M*T*KDiZ5@A zJK2`pe}>q9MsuD8z#tZRs){eG|G#oaaS+;Yx}tlvi)_>?`&g_|0$8pGJ_I9RLc+P`1Ue57Gw1W@IaQZOY1< zDgHMhRme5+Kd1D0e}NWaQW;y4z=PW#;>@ds2ThBuhI?o(NP-yn)sJvxLuGFVoVCjy zS2d!_M>=zZ%dO5gmX^<3FlkW#A!JMItH)$j$A-#M2E8@Q>K1A{bjnr5jW-~g{*wyr z9(@kP7k{Hnwec1U8XG!PHr;R@1=Vtk%dMp6gBRxe<`#|XDh4~9??WSUC(9Ght3^Py zx#)_Q18Q>GKi!7{*^M)S?WxSb?Kz;rMVZu_6d7+js9jV=>b0≦!)j)0i2^(6_4F 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⪼8)D-TJ`->@>Uw(8fCdv}Jn*&O4Gn>9R&mbhvv@|5CwbLtc zT+Cv#3`9_)uRYtkD#uzl*1!*`QQ&9q{K3jO=+~DCVyXK5Nwr6Jz1JP#%{V^kRk?WK zk1wAdXUG%)Uo=b*VVkj(it<5m*jbmmFMI|soRp3ewj4R&hvv_;U7I_@W6{w}I&?nG zLNkqDeRBQBOBYUs;7Egg+2OG#H{KP6UGYwtXixpBZ+GjCdh_|;wK^{TaqIK$WBy*> T_m77=o*i6O^uzS|W#GR6*1vMu literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index a38c787196..9429a691be 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -967,6 +967,10 @@ mobs:register_mob("mobs_mc:villager", { drops = {}, can_despawn = false, -- TODO: sounds + sounds = { + random = "mobs_mc_villager", + distance = 10, + }, animation = { stand_speed = 25, stand_start = 40, From 322578df6a9c1aff193bd41eeeaa7c387c66d737 Mon Sep 17 00:00:00 2001 From: Code-Sploit Date: Thu, 25 Mar 2021 16:03:54 +0000 Subject: [PATCH 009/234] Something even more secret! --- mods/ENTITIES/mobs_mc/sheep.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 84650b4ddd..963b3c26db 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -163,11 +163,11 @@ mobs:register_mob("mobs_mc:sheep", { self.initial_color_set = true end - local is_kay27 = self.nametag == "kay27" + local is_codesploit = self.nametag == "Code-Sploit" if self.color_change_timer then local old_color = self.color - if is_kay27 then + if is_codesploit then self.color_change_timer = self.color_change_timer - dtime if self.color_change_timer < 0 then self.color_change_timer = 0.5 @@ -184,7 +184,7 @@ mobs:register_mob("mobs_mc:sheep", { self.base_texture = sheep_texture(self.color) self.object:set_properties({textures = self.base_texture}) end - elseif is_kay27 then + elseif is_codesploit then self.initial_color = self.color self.color_change_timer = 0 self.color_index = -1 From d555fce8bc3cbf1c6485e829e014e7142c483e11 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 25 Mar 2021 17:29:15 +0100 Subject: [PATCH 010/234] Bruh. kay27 has 20 times more commits than you. This reverts commit 322578df6a9c1aff193bd41eeeaa7c387c66d737. --- mods/ENTITIES/mobs_mc/sheep.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 963b3c26db..84650b4ddd 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -163,11 +163,11 @@ mobs:register_mob("mobs_mc:sheep", { self.initial_color_set = true end - local is_codesploit = self.nametag == "Code-Sploit" + local is_kay27 = self.nametag == "kay27" if self.color_change_timer then local old_color = self.color - if is_codesploit then + if is_kay27 then self.color_change_timer = self.color_change_timer - dtime if self.color_change_timer < 0 then self.color_change_timer = 0.5 @@ -184,7 +184,7 @@ mobs:register_mob("mobs_mc:sheep", { self.base_texture = sheep_texture(self.color) self.object:set_properties({textures = self.base_texture}) end - elseif is_codesploit then + elseif is_kay27 then self.initial_color = self.color self.color_change_timer = 0 self.color_index = -1 From 630e7e8acb517a06aec56cad1839e05728e6f7a4 Mon Sep 17 00:00:00 2001 From: Code-Sploit Date: Thu, 25 Mar 2021 16:20:02 +0000 Subject: [PATCH 011/234] Do a secre thing even more secret then the secret thing of secret --- mods/ENTITIES/mobs_mc/sheep.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 84650b4ddd..963b3c26db 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -163,11 +163,11 @@ mobs:register_mob("mobs_mc:sheep", { self.initial_color_set = true end - local is_kay27 = self.nametag == "kay27" + local is_codesploit = self.nametag == "Code-Sploit" if self.color_change_timer then local old_color = self.color - if is_kay27 then + if is_codesploit then self.color_change_timer = self.color_change_timer - dtime if self.color_change_timer < 0 then self.color_change_timer = 0.5 @@ -184,7 +184,7 @@ mobs:register_mob("mobs_mc:sheep", { self.base_texture = sheep_texture(self.color) self.object:set_properties({textures = self.base_texture}) end - elseif is_kay27 then + elseif is_codesploit then self.initial_color = self.color self.color_change_timer = 0 self.color_index = -1 From 97991d138cf7294e7d85b0febc685399ead53ab9 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 25 Mar 2021 17:34:03 +0100 Subject: [PATCH 012/234] Revert "Do a secre thing even more secret then the secret thing of secret" This reverts commit 630e7e8acb517a06aec56cad1839e05728e6f7a4. --- mods/ENTITIES/mobs_mc/sheep.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 963b3c26db..84650b4ddd 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -163,11 +163,11 @@ mobs:register_mob("mobs_mc:sheep", { self.initial_color_set = true end - local is_codesploit = self.nametag == "Code-Sploit" + local is_kay27 = self.nametag == "kay27" if self.color_change_timer then local old_color = self.color - if is_codesploit then + if is_kay27 then self.color_change_timer = self.color_change_timer - dtime if self.color_change_timer < 0 then self.color_change_timer = 0.5 @@ -184,7 +184,7 @@ mobs:register_mob("mobs_mc:sheep", { self.base_texture = sheep_texture(self.color) self.object:set_properties({textures = self.base_texture}) end - elseif is_codesploit then + elseif is_kay27 then self.initial_color = self.color self.color_change_timer = 0 self.color_index = -1 From 86a18802dc790a9c2cead1466665082223eda41d Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Thu, 25 Mar 2021 21:57:07 +0100 Subject: [PATCH 013/234] use proper colors --- mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua index c5c3b3dc8a..bbecd07dcb 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua @@ -1,6 +1,8 @@ local S = minetest.get_translator("mesecons_commandblock") local F = minetest.formspec_escape +local color_red = mcl_colors.RED + local function construct(pos) local meta = minetest.get_meta(pos) @@ -78,7 +80,7 @@ local function check_commands(commands, player_name) if string.sub(cmd, 1, 1) == "/" then msg = S("Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.", cmd) end - return false, minetest.colorize("#FF0000", msg) + return false, minetest.colorize(color_red, msg) end if player_name then local player_privs = minetest.get_player_privs(player_name) @@ -86,7 +88,7 @@ local function check_commands(commands, player_name) for cmd_priv, _ in pairs(cmddef.privs) do if player_privs[cmd_priv] ~= true then local msg = S("Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.", cmd, cmd_priv) - return false, minetest.colorize("#FF0000", msg) + return false, minetest.colorize(color_red, msg) end end end From b9301f12ce1b65fac9d2319bcddab715d449a4be Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Thu, 25 Mar 2021 21:59:21 +0100 Subject: [PATCH 014/234] Update mod.conf --- mods/ITEMS/REDSTONE/mesecons_commandblock/mod.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/mod.conf b/mods/ITEMS/REDSTONE/mesecons_commandblock/mod.conf index 4a743406c7..a35c425f59 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/mod.conf +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/mod.conf @@ -1,3 +1,3 @@ name = mesecons_commandblock -depends = mesecons +depends = mesecons, mcl_colors optional_depends = doc, doc_items From e4a6244fddb16be0868f52d366f81b543ae4e160 Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Thu, 25 Mar 2021 22:07:38 +0100 Subject: [PATCH 015/234] add basic setting --- mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua | 2 ++ settingtypes.txt | 3 +++ 2 files changed, 5 insertions(+) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua index bbecd07dcb..247a0718b9 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua @@ -3,6 +3,8 @@ local F = minetest.formspec_escape local color_red = mcl_colors.RED +local command_blocks_activated = minetest.settings:get_bool("mcl_enable_commandblocks", true) + local function construct(pos) local meta = minetest.get_meta(pos) diff --git a/settingtypes.txt b/settingtypes.txt index af0e18d852..67e686d1eb 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -129,6 +129,9 @@ mcl_superflat_classic (Classic superflat map generation) bool false # If disabled, no ores will be generated. mcl_generate_ores (Generate Ores) bool true +# If disabled, command blocks will be unusuable (but still present). +mcl_enable_commandblocks (Enable Command Blocks) bool true + # Make some blocks emit decorative particles like flames. This setting # specifies the detail level of particles, with higher levels being # more CPU demanding. From 8258dae1b80afe2d58a3efd459b9cb0892247404 Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Thu, 25 Mar 2021 22:13:37 +0100 Subject: [PATCH 016/234] setting working --- .../REDSTONE/mesecons_commandblock/init.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua index 247a0718b9..481ed5d6ee 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua @@ -4,6 +4,7 @@ local F = minetest.formspec_escape local color_red = mcl_colors.RED local command_blocks_activated = minetest.settings:get_bool("mcl_enable_commandblocks", true) +local msg_not_activated = S("Command Blocks are not activated on the server") --TODO: real mc message and translation local function construct(pos) local meta = minetest.get_meta(pos) @@ -102,10 +103,15 @@ local function commandblock_action_on(pos, node) if node.name ~= "mesecons_commandblock:commandblock_off" then return end - - minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"}) - + local meta = minetest.get_meta(pos) + local commander = meta:get_string("commander") + + if not command_blocks_activated then + minetest.chat_send_player(commander, msg_not_activated) + return + end + minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"}) local commands = resolve_commands(meta:get_string("commands"), pos) for _, command in pairs(commands:split("\n")) do @@ -121,7 +127,6 @@ local function commandblock_action_on(pos, node) return end -- Execute command in the name of commander - local commander = meta:get_string("commander") cmddef.func(commander, param) end end @@ -133,6 +138,10 @@ local function commandblock_action_off(pos, node) end local on_rightclick = function(pos, node, player, itemstack, pointed_thing) + if not command_blocks_activated then + minetest.chat_send_player(player:get_player_name(), msg_not_activated) + return + end local can_edit = true -- Only allow write access in Creative Mode if not minetest.is_creative_enabled(player:get_player_name()) then From 25f6a9ee23cc899a5bd151ed8b1f9c0c939f8a89 Mon Sep 17 00:00:00 2001 From: kay27 Date: Fri, 26 Mar 2021 09:29:05 +0400 Subject: [PATCH 017/234] [mcl_core] Set obsidian.is_ground_content to false, see https://git.minetest.land/MineClone2/MineClone2/issues/1372 --- mods/ITEMS/mcl_core/nodes_base.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/nodes_base.lua b/mods/ITEMS/mcl_core/nodes_base.lua index cc6a0e6ae1..f4fe12155b 100644 --- a/mods/ITEMS/mcl_core/nodes_base.lua +++ b/mods/ITEMS/mcl_core/nodes_base.lua @@ -808,7 +808,7 @@ minetest.register_node("mcl_core:obsidian", { description = S("Obsidian"), _doc_items_longdesc = S("Obsidian is an extremely hard mineral with an enourmous blast-resistance. Obsidian is formed when water meets lava."), tiles = {"default_obsidian.png"}, - is_ground_content = true, + is_ground_content = false, sounds = mcl_sounds.node_sound_stone_defaults(), stack_max = 64, groups = {pickaxey=5, building_block=1, material_stone=1}, From 0e5bbd6d3df2d5332073ff684eb6746bb36eddbc Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Fri, 26 Mar 2021 09:57:28 +0100 Subject: [PATCH 018/234] fix msg to be mc like https://www.digminecraft.com/game_commands/enable_command_blocks.php --- mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua index 481ed5d6ee..58355dafc2 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua @@ -4,7 +4,7 @@ local F = minetest.formspec_escape local color_red = mcl_colors.RED local command_blocks_activated = minetest.settings:get_bool("mcl_enable_commandblocks", true) -local msg_not_activated = S("Command Blocks are not activated on the server") --TODO: real mc message and translation +local msg_not_activated = S("Command blocks are not enabled on this server") --TODO: translation local function construct(pos) local meta = minetest.get_meta(pos) From 78bad87a72b0c322ef5b034c393e08c2501cdf98 Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Fri, 26 Mar 2021 09:59:58 +0100 Subject: [PATCH 019/234] fix transation --- mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua | 2 +- .../mesecons_commandblock/locale/mesecons_commandblock.de.tr | 1 + .../mesecons_commandblock/locale/mesecons_commandblock.es.tr | 1 + .../mesecons_commandblock/locale/mesecons_commandblock.fr.tr | 1 + .../mesecons_commandblock/locale/mesecons_commandblock.ru.tr | 1 + mods/ITEMS/REDSTONE/mesecons_commandblock/locale/template.txt | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua index 58355dafc2..4b389090d2 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua @@ -4,7 +4,7 @@ local F = minetest.formspec_escape local color_red = mcl_colors.RED local command_blocks_activated = minetest.settings:get_bool("mcl_enable_commandblocks", true) -local msg_not_activated = S("Command blocks are not enabled on this server") --TODO: translation +local msg_not_activated = S("Command blocks are not enabled on this server") local function construct(pos) local meta = minetest.get_meta(pos) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.de.tr b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.de.tr index 9c9b1df1de..a149feef94 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.de.tr +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.de.tr @@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.=Zugr Editing the command block has failed! You can only change the command block in Creative Mode!=Bearbeitung des Befehlsblocks fehlgeschlagen! Sie können den Befehlsblock nur im Kreativmodus ändern! Editing the command block has failed! The command block is gone.=Bearbeiten des Befehlsblocks fehlgeschlagen! Der Befehlsblock ist verschwunden. Executes server commands when powered by redstone power=Führt Serverbefehle aus, wenn mit Redstoneenergie versorgt +Command blocks are not enabled on this server= diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.es.tr b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.es.tr index 8826ab9a68..938c710b94 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.es.tr +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.es.tr @@ -28,3 +28,4 @@ Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=2. Access denied. You need the “maphack” privilege to edit command blocks.=Acceso denegado. Necesita el privilegio "maphack" para editar bloques de comandos. Editing the command block has failed! You can only change the command block in Creative Mode!=¡La edición del bloque de comando ha fallado! ¡Solo puede cambiar el bloque de comandos en modo creativo! Editing the command block has failed! The command block is gone.=¡La edición del bloque de comando ha fallado! El bloque de comando se ha ido. +Command blocks are not enabled on this server= diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.fr.tr b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.fr.tr index 061ac08a04..b397c979ca 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.fr.tr +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.fr.tr @@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.=Acc Editing the command block has failed! You can only change the command block in Creative Mode!=La modification du bloc de commandes a échoué! Vous ne pouvez modifier le bloc de commandes qu'en mode créatif! Editing the command block has failed! The command block is gone.=La modification du bloc de commandes a échoué! Le bloc de commande a disparu. Executes server commands when powered by redstone power=Exécute les commandes du serveur lorsqu'il est alimenté par l'alimentation Redstone +Command blocks are not enabled on this server=Les blocks de commandes ne sont pas activés sur ce serveur diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.ru.tr b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.ru.tr index 8671099c73..85bed4b95c 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.ru.tr +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/mesecons_commandblock.ru.tr @@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.=До Editing the command block has failed! You can only change the command block in Creative Mode!=Попытка редактирования командного блока потерпела неудачу. Вы можете изменять командные блоки только в творческом режиме! Editing the command block has failed! The command block is gone.=Попытка редактирования командного блока потерпела неудачу. Командный блок исчез. Executes server commands when powered by redstone power=При подаче энергии редстоуна выполняет серверные команды +Command blocks are not enabled on this server= diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/template.txt b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/template.txt index 0e0c3caa52..49e98ef2b0 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/template.txt +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/locale/template.txt @@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.= Editing the command block has failed! You can only change the command block in Creative Mode!= Editing the command block has failed! The command block is gone.= Executes server commands when powered by redstone power= +Command blocks are not enabled on this server= From 53d7134437ef11f05506ea1eb7d45dd28dee1bc9 Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Fri, 26 Mar 2021 10:00:48 +0100 Subject: [PATCH 020/234] remove unuseful spamming messages --- mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua index 4b389090d2..1928f809cf 100644 --- a/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_commandblock/init.lua @@ -108,7 +108,7 @@ local function commandblock_action_on(pos, node) local commander = meta:get_string("commander") if not command_blocks_activated then - minetest.chat_send_player(commander, msg_not_activated) + --minetest.chat_send_player(commander, msg_not_activated) return end minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"}) From c0308c7c0821b032e5bd7dc0778fc113ac04eabc Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Fri, 26 Mar 2021 11:49:41 +0100 Subject: [PATCH 021/234] fix weird death message (#1378) --- mods/HUD/mcl_death_messages/init.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/mods/HUD/mcl_death_messages/init.lua b/mods/HUD/mcl_death_messages/init.lua index b2c656ac41..8ca6867019 100644 --- a/mods/HUD/mcl_death_messages/init.lua +++ b/mods/HUD/mcl_death_messages/init.lua @@ -1,5 +1,8 @@ local S = minetest.get_translator("mcl_death_messages") local N = function(s) return s end +local C = minetest.colorize + +local color_skyblue = mcl_colors.AQUA local function get_tool_name(item) local name = item:get_meta():get_string("name") @@ -41,6 +44,9 @@ local msgs = { ["murder"] = { N("@1 was slain by @2 using [@3]"), }, + ["murder_hand"] = { + N("@1 was slain by @2"), + }, ["murder_any"] = { N("@1 was killed."), }, @@ -131,7 +137,7 @@ local last_damages = { } minetest.register_on_dieplayer(function(player, reason) -- Death message - local message = minetest.settings:get_bool("mcl_showDeathMessages") + local message = minetest.settings:get_bool("mcl_showDeathMessages") --Maybe cache the setting? if message == nil then message = true end @@ -201,7 +207,11 @@ minetest.register_on_dieplayer(function(player, reason) elseif hitter:is_player() then hittername = hitter:get_player_name() if hittername ~= nil then - msg = dmsg("murder", name, hittername, minetest.colorize("#00FFFF", hitter_toolname)) + if hitter_toolname == "" then + msg = dmsg("murder_hand", name, hittername) + else + msg = dmsg("murder", name, hittername, C(color_skyblue, hitter_toolname)) + end else msg = dmsg("murder_any", name) end @@ -229,7 +239,7 @@ minetest.register_on_dieplayer(function(player, reason) if shooter == nil then msg = dmsg("arrow", name) elseif shooter:is_player() then - msg = dmsg("arrow_name", name, shooter:get_player_name(), minetest.colorize("#00FFFF", get_tool_name(shooter:get_wielded_item()))) + msg = dmsg("arrow_name", name, shooter:get_player_name(), C(color_skyblue, get_tool_name(shooter:get_wielded_item()))) elseif s_ent and s_ent._cmi_is_mob then if s_ent.nametag ~= "" then msg = dmsg("arrow_name", name, shooter:get_player_name(), get_tool_name(shooter:get_wielded_item())) From 41768e95a109b0a06c4ea0fb19098f4a52860cb6 Mon Sep 17 00:00:00 2001 From: AFCMS <61794590+AFCMS@users.noreply.github.com> Date: Fri, 26 Mar 2021 11:50:14 +0100 Subject: [PATCH 022/234] fix --- mods/HUD/mcl_death_messages/locale/mcl_death_messages.de.tr | 1 + mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr | 1 + mods/HUD/mcl_death_messages/locale/mcl_death_messages.fr.tr | 1 + mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr | 1 + mods/HUD/mcl_death_messages/locale/template.txt | 1 + mods/HUD/mcl_death_messages/mod.conf | 1 + 6 files changed, 6 insertions(+) diff --git a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.de.tr b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.de.tr index b9ef6680df..ffb567b8be 100644 --- a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.de.tr +++ b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.de.tr @@ -56,3 +56,4 @@ A ghast scared @1 to death.=Ein Ghast hat @1 zu Tode erschrocken. @1 was killed by a baby husk.=@1 wurde von einem Wüstenzombiebaby getötet. @1 was killed by a zombie pigman.=@1 wurde von einem Schweinezombie getötet. @1 was killed by a baby zombie pigman.=@1 wurde von einem Schweinezombiebaby getötet. +@1 was slain by @2.= diff --git a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr index 6ed106db88..a56199e009 100644 --- a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr +++ b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr @@ -55,3 +55,4 @@ A ghast scared @1 to death.=Se ha asustado @1 hasta morir. @1 was killed by a baby husk.=@1 fue asesinado por un bebé husk. @1 was killed by a zombie pigman.=@1 fue asesinado por un cerdo zombie. @1 was killed by a baby zombie pigman.=@1 fue asesinado por un bebé cerdo zombie. +@1 was slain by @2.= diff --git a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.fr.tr b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.fr.tr index 6d0a5115c1..05cf999767 100644 --- a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.fr.tr +++ b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.fr.tr @@ -56,3 +56,4 @@ A ghast scared @1 to death.=Un ghast a éffrayé @1 à mort. @1 was killed by a baby husk.=@1 a été tué par un bébé zombie momie. @1 was killed by a zombie pigman.=@1 a été tué par un zombie-couchon. @1 was killed by a baby zombie pigman.=@1 a été tué par un bébé zombie-couchon +@1 was slain by @2.= diff --git a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr index f9f164dd3d..d5b6ec3963 100644 --- a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr +++ b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr @@ -56,3 +56,4 @@ A ghast scared @1 to death.=Гаст напугал @1 до смерти. @1 was killed by a baby husk.=@1 был(а) убит(а) машылом-кадавром. @1 was killed by a zombie pigman.=@1 был(а) убит(а) зомби-свиночеловеком. @1 was killed by a baby zombie pigman.=@1 был(а) убит(а) малышом-зомби-свиночеловеком. +@1 was slain by @2.= diff --git a/mods/HUD/mcl_death_messages/locale/template.txt b/mods/HUD/mcl_death_messages/locale/template.txt index db074f756f..d1e3b832ba 100644 --- a/mods/HUD/mcl_death_messages/locale/template.txt +++ b/mods/HUD/mcl_death_messages/locale/template.txt @@ -56,3 +56,4 @@ A ghast scared @1 to death.= @1 was killed by a baby husk.= @1 was killed by a zombie pigman.= @1 was killed by a baby zombie pigman.= +@1 was slain by @2.= diff --git a/mods/HUD/mcl_death_messages/mod.conf b/mods/HUD/mcl_death_messages/mod.conf index 23d2852e79..a634e16dea 100644 --- a/mods/HUD/mcl_death_messages/mod.conf +++ b/mods/HUD/mcl_death_messages/mod.conf @@ -1,3 +1,4 @@ name = mcl_death_messages author = 4Evergreen4 description = Shows messages in chat when a player dies. +depends = mcl_colors From 01eba30058ee57af7a4957f7961e26196f6227cd Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 14:32:08 +0100 Subject: [PATCH 023/234] Fix #1234 --- mods/HUD/mcl_inventory/creative.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index 1cebed0cdc..b3ee40bf7f 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -489,8 +489,8 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz if filter == nil then filter = "" end - formspec = formspec .. "field[5.3,1.34;4,0.75;suche;;"..minetest.formspec_escape(filter).."]" - formspec = formspec .. "field_close_on_enter[suche;false]" + formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]" + formspec = formspec .. "field_close_on_enter[search;false]" end if pagenum ~= nil then formspec = formspec .. "p"..tostring(pagenum) end @@ -561,11 +561,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) elseif fields.inv then if players[name].page == "inv" then return end page = "inv" - elseif fields.suche == "" and not fields.creative_next and not fields.creative_prev then + elseif fields.search == "" and not fields.creative_next and not fields.creative_prev then set_inv_page("all", player) page = "nix" - elseif fields.suche ~= nil and not fields.creative_next and not fields.creative_prev then - set_inv_search(string.lower(fields.suche),player) + elseif fields.search ~= nil and not fields.creative_next and not fields.creative_prev then + set_inv_search(string.lower(fields.search),player) page = "nix" end @@ -612,8 +612,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) players[name].start_i = start_i local filter = "" - if not fields.nix and fields.suche ~= nil and fields.suche ~= "" then - filter = fields.suche + if not fields.nix and fields.search ~= nil and fields.search ~= "" then + filter = fields.search players[name].filter = filter end From 88fc515cff20edb16d627a7973f10575618678e6 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 17:38:25 +0100 Subject: [PATCH 024/234] make mobs take damage of falling anvils --- mods/ENTITIES/mcl_falling_nodes/init.lua | 71 +++++++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_falling_nodes/init.lua b/mods/ENTITIES/mcl_falling_nodes/init.lua index 1ffc87b34b..8f72cc13d5 100644 --- a/mods/ENTITIES/mcl_falling_nodes/init.lua +++ b/mods/ENTITIES/mcl_falling_nodes/init.lua @@ -13,9 +13,8 @@ local deal_falling_damage = function(self, dtime) if minetest.get_item_group(self.node.name, "falling_node_damage") == 0 then return end - -- Cause damage to any player it hits. + -- Cause damage to any entity it hits. -- Algorithm based on MC anvils. - -- TODO: Support smashing other objects, too. local pos = self.object:get_pos() if not self._startpos then -- Fallback @@ -23,6 +22,72 @@ local deal_falling_damage = function(self, dtime) end local objs = minetest.get_objects_inside_radius(pos, 1) for _,v in ipairs(objs) do + if v:is_player() then + local hp = v:get_hp() + local name = v:get_player_name() + if hp ~= 0 then + if not self._hit_players then + self._hit_players = {} + end + local hit = false + for _,v in ipairs(self._hit_players) do + if name == v then + hit = true + end + end + if not hit then + table.insert(self._hit_players, name) + local way = self._startpos.y - pos.y + local damage = (way - 1) * 2 + damage = math.min(40, math.max(0, damage)) + if damage >= 1 then + hp = hp - damage + if hp < 0 then + hp = 0 + end + -- TODO: Reduce damage if wearing a helmet + local msg + if minetest.get_item_group(self.node.name, "anvil") ~= 0 then + msg = S("@1 was smashed by a falling anvil.", v:get_player_name()) + else + msg = S("@1 was smashed by a falling block.", v:get_player_name()) + end + if dmes then + mcl_death_messages.player_damage(v, msg) + end + v:set_hp(hp, { type = "punch", from = "mod" }) + end + end + end + else + local hp = v:get_luaentity().health + if hp and hp ~= 0 then + if not self._hit_mobs then + self._hit_mobs = {} + end + local hit = false + for _,mob in ipairs(self._hit_mobs) do + if v == mob then + hit = true + end + end + if not hit then + table.insert(self._hit_mobs, v) + local way = self._startpos.y - pos.y + local damage = (way - 1) * 2 + damage = math.min(40, math.max(0, damage)) + if damage >= 1 then + hp = hp - damage + if hp < 0 then + hp = 0 + end + v:get_luaentity().health = hp + end + end + end + end + end +--[[ for _,v in ipairs(objs) do local hp = v:get_hp() if v:is_player() and hp ~= 0 then if not self._hit_players then @@ -61,7 +126,7 @@ local deal_falling_damage = function(self, dtime) end end end - end + end ]] end minetest.register_entity(":__builtin:falling_node", { From 041300cde4918b5b0b6ee9fec6f411c01fcd9ede Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 17:39:25 +0100 Subject: [PATCH 025/234] remove unuseful code --- mods/ENTITIES/mcl_falling_nodes/init.lua | 40 ------------------------ 1 file changed, 40 deletions(-) diff --git a/mods/ENTITIES/mcl_falling_nodes/init.lua b/mods/ENTITIES/mcl_falling_nodes/init.lua index 8f72cc13d5..f173cbadef 100644 --- a/mods/ENTITIES/mcl_falling_nodes/init.lua +++ b/mods/ENTITIES/mcl_falling_nodes/init.lua @@ -87,46 +87,6 @@ local deal_falling_damage = function(self, dtime) end end end ---[[ for _,v in ipairs(objs) do - local hp = v:get_hp() - if v:is_player() and hp ~= 0 then - if not self._hit_players then - self._hit_players = {} - end - local name = v:get_player_name() - local hit = false - for _,v in ipairs(self._hit_players) do - if name == v then - hit = true - end - end - if not hit then - table.insert(self._hit_players, name) - local way = self._startpos.y - pos.y - local damage = (way - 1) * 2 - damage = math.min(40, math.max(0, damage)) - if damage >= 1 then - hp = hp - damage - if hp < 0 then - hp = 0 - end - if v:is_player() then - -- TODO: Reduce damage if wearing a helmet - local msg - if minetest.get_item_group(self.node.name, "anvil") ~= 0 then - msg = S("@1 was smashed by a falling anvil.", v:get_player_name()) - else - msg = S("@1 was smashed by a falling block.", v:get_player_name()) - end - if dmes then - mcl_death_messages.player_damage(v, msg) - end - end - v:set_hp(hp, { type = "punch", from = "mod" }) - end - end - end - end ]] end minetest.register_entity(":__builtin:falling_node", { From 6f8d0d4de0a3f5e93557aea40c91e26d4468cc48 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Fri, 26 Mar 2021 17:51:13 +0100 Subject: [PATCH 026/234] Fix #1375 --- mods/ENTITIES/mcl_boats/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index 9a9b65cc9b..29d5c2256a 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -247,7 +247,7 @@ function boat.on_step(self, dtime, moveresult) else local ctrl = self._passenger:get_player_control() if ctrl and ctrl.sneak then - detach_player(self._passenger, true) + detach_object(self._passenger, true) self._passenger = nil end end From 8c002671c0e16f805788be2ea2966c4b6712bd2e Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 18:24:08 +0100 Subject: [PATCH 027/234] make helmet protect from falling anvils --- mods/ENTITIES/mcl_falling_nodes/init.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_falling_nodes/init.lua b/mods/ENTITIES/mcl_falling_nodes/init.lua index f173cbadef..5b94373d95 100644 --- a/mods/ENTITIES/mcl_falling_nodes/init.lua +++ b/mods/ENTITIES/mcl_falling_nodes/init.lua @@ -1,5 +1,8 @@ local S = minetest.get_translator("mcl_falling_nodes") local dmes = minetest.get_modpath("mcl_death_messages") ~= nil +local has_mcl_armor = minetest.get_modpath("mcl_armor") + +local his_creative_enabled = minetest.is_creative_enabled local get_falling_depth = function(self) if not self._startpos then @@ -45,7 +48,16 @@ local deal_falling_damage = function(self, dtime) if hp < 0 then hp = 0 end - -- TODO: Reduce damage if wearing a helmet + -- Reduce damage if wearing a helmet + local inv = v:get_inventory() + local helmet = inv:get_stack("armor", 2) + if has_mcl_armor and not helmet:is_empty() then + hp = hp/4*3 + if not his_creative_enabled(name) then + helmet:add_wear(65535/helmet:get_definition().groups.mcl_armor_uses) --TODO: be sure damage is exactly like mc (informations are missing in the mc wiki) + inv:set_stack("armor", 2, helmet) + end + end local msg if minetest.get_item_group(self.node.name, "anvil") ~= 0 then msg = S("@1 was smashed by a falling anvil.", v:get_player_name()) @@ -71,6 +83,7 @@ local deal_falling_damage = function(self, dtime) hit = true end end + --TODO: reduce damage for mobs then they will be able to wear armor if not hit then table.insert(self._hit_mobs, v) local way = self._startpos.y - pos.y From 202e30a78211a4f44a902e4843baf54a27abb24a Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 21:37:10 +0100 Subject: [PATCH 028/234] Add API to mcl_tmp_message --- mods/HUD/mcl_tmp_message/API.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 mods/HUD/mcl_tmp_message/API.md diff --git a/mods/HUD/mcl_tmp_message/API.md b/mods/HUD/mcl_tmp_message/API.md new file mode 100644 index 0000000000..0a3fc06a33 --- /dev/null +++ b/mods/HUD/mcl_tmp_message/API.md @@ -0,0 +1,7 @@ +# mcl_temp_message + +Allow mods to show short messages in the hud of players. + +## mcl_tmp_message.message(player, message) + +Show above the hotbar a hud message to player . \ No newline at end of file From e3c99c5be212e4882257c5ccf7cc971bb36fe4cc Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 22:31:15 +0100 Subject: [PATCH 029/234] add basic API to mcl_throwing remove hard depends to mcl_fishing --- mods/ITEMS/mcl_fishing/init.lua | 48 +++- mods/ITEMS/mcl_fishing/mod.conf | 2 +- mods/ITEMS/mcl_throwing/API.md | 3 + mods/ITEMS/mcl_throwing/init.lua | 398 +-------------------------- mods/ITEMS/mcl_throwing/mod.conf | 2 +- mods/ITEMS/mcl_throwing/register.lua | 335 ++++++++++++++++++++++ 6 files changed, 398 insertions(+), 390 deletions(-) create mode 100644 mods/ITEMS/mcl_throwing/API.md create mode 100644 mods/ITEMS/mcl_throwing/register.lua diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index 1ff56c2773..d431ee10c9 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -173,7 +173,7 @@ local fish = function(itemstack, player, pointed_thing) if noent == true then local playerpos = player:get_pos() local dir = player:get_look_dir() - local obj = mcl_throwing.throw("mcl_throwing:flying_bobber", {x=playerpos.x, y=playerpos.y+1.5, z=playerpos.z}, dir, 15, player:get_player_name()) + local obj = mcl_throwing.throw("mcl_fishing:flying_bobber", {x=playerpos.x, y=playerpos.y+1.5, z=playerpos.z}, dir, 15, player:get_player_name()) end end @@ -295,6 +295,52 @@ bobber_ENTITY.on_step = bobber_on_step minetest.register_entity("mcl_fishing:bobber_entity", bobber_ENTITY) +local flying_bobber_ENTITY={ + physical = false, + timer=0, + textures = {"mcl_fishing_bobber.png"}, --FIXME: Replace with correct texture. + visual_size = {x=0.5, y=0.5}, + collisionbox = {0,0,0,0,0,0}, + pointable = false, + + get_staticdata = get_staticdata, + on_activate = on_activate, + + _lastpos={}, + _thrower = nil, + objtype="fishing", +} + +-- Movement function of flying bobber +local flying_bobber_on_step = function(self, dtime) + self.timer=self.timer+dtime + local pos = self.object:get_pos() + local node = minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] + --local player = minetest.get_player_by_name(self._thrower) + + -- Destroy when hitting a solid node + if self._lastpos.x~=nil then + if (def and (def.walkable or def.liquidtype == "flowing" or def.liquidtype == "source")) or not def then + local make_child= function(object) + local ent = object:get_luaentity() + ent.player = self._thrower + ent.child = true + end + make_child(minetest.add_entity(self._lastpos, "mcl_fishing:bobber_entity")) + self.object:remove() + return + end + end + self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node +end + +flying_bobber_ENTITY.on_step = flying_bobber_on_step + +minetest.register_entity("mcl_fishing:flying_bobber_entity", flying_bobber_ENTITY) + +mcl_throwing.register_throwable_object("mcl_fishing:flying_bobber", "mcl_fishing:flying_bobber_entity", 5) + -- If player leaves area, remove bobber. minetest.register_on_leaveplayer(function(player) local objs = minetest.get_objects_inside_radius(player:get_pos(), 250) diff --git a/mods/ITEMS/mcl_fishing/mod.conf b/mods/ITEMS/mcl_fishing/mod.conf index 56a3305a07..65c2f68a9f 100644 --- a/mods/ITEMS/mcl_fishing/mod.conf +++ b/mods/ITEMS/mcl_fishing/mod.conf @@ -1,3 +1,3 @@ name = mcl_fishing description = Adds fish and fishing poles to go fishing. -depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting +depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting, mcl_throwing diff --git a/mods/ITEMS/mcl_throwing/API.md b/mods/ITEMS/mcl_throwing/API.md new file mode 100644 index 0000000000..a75a71635e --- /dev/null +++ b/mods/ITEMS/mcl_throwing/API.md @@ -0,0 +1,3 @@ +# mcl_throwing + +## mcl_throwing.throw(throw_item, pos, dir, velocity, thrower) \ No newline at end of file diff --git a/mods/ITEMS/mcl_throwing/init.lua b/mods/ITEMS/mcl_throwing/init.lua index 5fe34b45e3..4d6dcfe5c9 100644 --- a/mods/ITEMS/mcl_throwing/init.lua +++ b/mods/ITEMS/mcl_throwing/init.lua @@ -2,7 +2,7 @@ mcl_throwing = {} local S = minetest.get_translator("mcl_throwing") local mod_death_messages = minetest.get_modpath("mcl_death_messages") -local mod_fishing = minetest.get_modpath("mcl_fishing") +local modpath = minetest.get_modpath(minetest.get_current_modname()) -- -- Snowballs and other throwable items @@ -10,21 +10,15 @@ local mod_fishing = minetest.get_modpath("mcl_fishing") local GRAVITY = tonumber(minetest.settings:get("movement_gravity")) -local entity_mapping = { - ["mcl_throwing:flying_bobber"] = "mcl_throwing:flying_bobber_entity", - ["mcl_throwing:snowball"] = "mcl_throwing:snowball_entity", - ["mcl_throwing:egg"] = "mcl_throwing:egg_entity", - ["mcl_throwing:ender_pearl"] = "mcl_throwing:ender_pearl_entity", -} +local entity_mapping = {} +local velocities = {} -local velocities = { - ["mcl_throwing:flying_bobber_entity"] = 5, - ["mcl_throwing:snowball_entity"] = 22, - ["mcl_throwing:egg_entity"] = 22, - ["mcl_throwing:ender_pearl_entity"] = 22, -} +function mcl_throwing.register_throwable_object(name, entity, velocity) + entity_mapping[name] = entity + velocities[name] = velocity +end -mcl_throwing.throw = function(throw_item, pos, dir, velocity, thrower) +function mcl_throwing.throw(throw_item, pos, dir, velocity, thrower) if velocity == nil then velocity = velocities[throw_item] end @@ -44,7 +38,7 @@ mcl_throwing.throw = function(throw_item, pos, dir, velocity, thrower) end -- Throw item -local player_throw_function = function(entity_name, velocity) +function mcl_throwing.get_player_throw_function(entity_name, velocity) local func = function(item, player, pointed_thing) local playerpos = player:get_pos() local dir = player:get_look_dir() @@ -57,7 +51,7 @@ local player_throw_function = function(entity_name, velocity) return func end -local dispense_function = function(stack, dispenserpos, droppos, dropnode, dropdir) +function mcl_throwing.dispense_function(stack, dispenserpos, droppos, dropnode, dropdir) -- Launch throwable item local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51)) mcl_throwing.throw(stack:get_name(), shootpos, dropdir) @@ -85,374 +79,4 @@ local on_activate = function(self, staticdata, dtime_s) end end --- The snowball entity -local snowball_ENTITY={ - physical = false, - timer=0, - textures = {"mcl_throwing_snowball.png"}, - visual_size = {x=0.5, y=0.5}, - collisionbox = {0,0,0,0,0,0}, - pointable = false, - - get_staticdata = get_staticdata, - on_activate = on_activate, - _thrower = nil, - - _lastpos={}, -} -local egg_ENTITY={ - physical = false, - timer=0, - textures = {"mcl_throwing_egg.png"}, - visual_size = {x=0.45, y=0.45}, - collisionbox = {0,0,0,0,0,0}, - pointable = false, - - get_staticdata = get_staticdata, - on_activate = on_activate, - _thrower = nil, - - _lastpos={}, -} --- Ender pearl entity -local pearl_ENTITY={ - physical = false, - timer=0, - textures = {"mcl_throwing_ender_pearl.png"}, - visual_size = {x=0.9, y=0.9}, - collisionbox = {0,0,0,0,0,0}, - pointable = false, - - get_staticdata = get_staticdata, - on_activate = on_activate, - - _lastpos={}, - _thrower = nil, -- Player ObjectRef of the player who threw the ender pearl -} - -local flying_bobber_ENTITY={ - physical = false, - timer=0, - textures = {"mcl_fishing_bobber.png"}, --FIXME: Replace with correct texture. - visual_size = {x=0.5, y=0.5}, - collisionbox = {0,0,0,0,0,0}, - pointable = false, - - get_staticdata = get_staticdata, - on_activate = on_activate, - - _lastpos={}, - _thrower = nil, - objtype="fishing", -} - -local check_object_hit = function(self, pos, dmg) - for _,object in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do - - local entity = object:get_luaentity() - - if entity - and entity.name ~= self.object:get_luaentity().name then - - if object:is_player() and self._thrower ~= object:get_player_name() then - -- TODO: Deal knockback - self.object:remove() - return true - elseif (entity._cmi_is_mob == true or entity._hittable_by_projectile) and (self._thrower ~= object) then - -- FIXME: Knockback is broken - object:punch(self.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = dmg, - }, nil) - return true - end - end - end - return false -end - -local snowball_particles = function(pos, vel) - local vel = vector.normalize(vector.multiply(vel, -1)) - minetest.add_particlespawner({ - amount = 20, - time = 0.001, - minpos = pos, - maxpos = pos, - minvel = vector.add({x=-2, y=3, z=-2}, vel), - maxvel = vector.add({x=2, y=5, z=2}, vel), - minacc = {x=0, y=-9.81, z=0}, - maxacc = {x=0, y=-9.81, z=0}, - minexptime = 1, - maxexptime = 3, - minsize = 0.7, - maxsize = 0.7, - collisiondetection = true, - collision_removal = true, - object_collision = false, - texture = "weather_pack_snow_snowflake"..math.random(1,2)..".png", - }) -end - --- Snowball on_step()--> called when snowball is moving. -local snowball_on_step = function(self, dtime) - self.timer=self.timer+dtime - local pos = self.object:get_pos() - local vel = self.object:get_velocity() - local node = minetest.get_node(pos) - local def = minetest.registered_nodes[node.name] - - - -- Destroy when hitting a solid node - if self._lastpos.x~=nil then - if (def and def.walkable) or not def then - minetest.sound_play("mcl_throwing_snowball_impact_hard", { pos = pos, max_hear_distance=16, gain=0.7 }, true) - snowball_particles(self._lastpos, vel) - self.object:remove() - return - end - end - - if check_object_hit(self, pos, {snowball_vulnerable = 3}) then - minetest.sound_play("mcl_throwing_snowball_impact_soft", { pos = pos, max_hear_distance=16, gain=0.7 }, true) - snowball_particles(pos, vel) - self.object:remove() - return - end - - self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set _lastpos-->Node will be added at last pos outside the node -end - --- Movement function of egg -local egg_on_step = function(self, dtime) - self.timer=self.timer+dtime - local pos = self.object:get_pos() - local node = minetest.get_node(pos) - local def = minetest.registered_nodes[node.name] - - -- Destroy when hitting a solid node with chance to spawn chicks - if self._lastpos.x~=nil then - if (def and def.walkable) or not def then - -- 1/8 chance to spawn a chick - -- FIXME: Chicks have a quite good chance to spawn in walls - local r = math.random(1,8) - - -- Turn given object into a child - local make_child= function(object) - local ent = object:get_luaentity() - object:set_properties({ - visual_size = { x = ent.base_size.x/2, y = ent.base_size.y/2 }, - collisionbox = { - ent.base_colbox[1]/2, - ent.base_colbox[2]/2, - ent.base_colbox[3]/2, - ent.base_colbox[4]/2, - ent.base_colbox[5]/2, - ent.base_colbox[6]/2, - } - }) - ent.child = true - end - if r == 1 then - make_child(minetest.add_entity(self._lastpos, "mobs_mc:chicken")) - - -- BONUS ROUND: 1/32 chance to spawn 3 additional chicks - local r = math.random(1,32) - if r == 1 then - local offsets = { - { x=0.7, y=0, z=0 }, - { x=-0.7, y=0, z=-0.7 }, - { x=-0.7, y=0, z=0.7 }, - } - for o=1, 3 do - local pos = vector.add(self._lastpos, offsets[o]) - make_child(minetest.add_entity(pos, "mobs_mc:chicken")) - end - end - end - minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true) - self.object:remove() - return - end - end - - -- Destroy when hitting a mob or player (no chick spawning) - if check_object_hit(self, pos) then - minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true) - self.object:remove() - return - end - - self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node -end - --- Movement function of ender pearl -local pearl_on_step = function(self, dtime) - self.timer=self.timer+dtime - local pos = self.object:get_pos() - pos.y = math.floor(pos.y) - local node = minetest.get_node(pos) - local nn = node.name - local def = minetest.registered_nodes[node.name] - - -- Destroy when hitting a solid node - if self._lastpos.x~=nil then - local walkable = (def and def.walkable) - - -- No teleport for hitting ignore for now. Otherwise the player could get stuck. - -- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas - if node.name == "ignore" then - self.object:remove() - -- Activate when hitting a solid node or a plant - elseif walkable or nn == "mcl_core:vine" or nn == "mcl_core:deadbush" or minetest.get_item_group(nn, "flower") ~= 0 or minetest.get_item_group(nn, "sapling") ~= 0 or minetest.get_item_group(nn, "plant") ~= 0 or minetest.get_item_group(nn, "mushroom") ~= 0 or not def then - local player = minetest.get_player_by_name(self._thrower) - if player then - -- Teleport and hurt player - - -- First determine good teleport position - local dir = {x=0, y=0, z=0} - - local v = self.object:get_velocity() - if walkable then - local vc = table.copy(v) -- vector for calculating - -- Node is walkable, we have to find a place somewhere outside of that node - vc = vector.normalize(vc) - - -- Zero-out the two axes with a lower absolute value than - -- the axis with the strongest force - local lv, ld - lv, ld = math.abs(vc.y), "y" - if math.abs(vc.x) > lv then - lv, ld = math.abs(vc.x), "x" - end - if math.abs(vc.z) > lv then - lv, ld = math.abs(vc.z), "z" - end - if ld ~= "x" then vc.x = 0 end - if ld ~= "y" then vc.y = 0 end - if ld ~= "z" then vc.z = 0 end - - -- Final tweaks to the teleporting pos, based on direction - -- Impact from the side - dir.x = vc.x * -1 - dir.z = vc.z * -1 - - -- Special case: top or bottom of node - if vc.y > 0 then - -- We need more space when impact is from below - dir.y = -2.3 - elseif vc.y < 0 then - -- Standing on top - dir.y = 0.5 - end - end - -- If node was not walkable, no modification to pos is made. - - -- Final teleportation position - local telepos = vector.add(pos, dir) - local telenode = minetest.get_node(telepos) - - --[[ It may be possible that telepos is walkable due to the algorithm. - Especially when the ender pearl is faster horizontally than vertical. - This applies final fixing, just to be sure we're not in a walkable node ]] - if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then - if v.y < 0 then - telepos.y = telepos.y + 0.5 - else - telepos.y = telepos.y - 2.3 - end - end - - local oldpos = player:get_pos() - -- Teleport and hurt player - player:set_pos(telepos) - player:set_hp(player:get_hp() - 5, { type = "fall", from = "mod" }) - - -- 5% chance to spawn endermite at the player's origin - local r = math.random(1,20) - if r == 1 then - minetest.add_entity(oldpos, "mobs_mc:endermite") - end - - end - self.object:remove() - return - end - end - self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node -end - --- Movement function of flying bobber -local flying_bobber_on_step = function(self, dtime) - self.timer=self.timer+dtime - local pos = self.object:get_pos() - local node = minetest.get_node(pos) - local def = minetest.registered_nodes[node.name] - --local player = minetest.get_player_by_name(self._thrower) - - -- Destroy when hitting a solid node - if self._lastpos.x~=nil then - if (def and (def.walkable or def.liquidtype == "flowing" or def.liquidtype == "source")) or not def then - local make_child= function(object) - local ent = object:get_luaentity() - ent.player = self._thrower - ent.child = true - end - make_child(minetest.add_entity(self._lastpos, "mcl_fishing:bobber_entity")) - self.object:remove() - return - end - end - self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node -end - -snowball_ENTITY.on_step = snowball_on_step -egg_ENTITY.on_step = egg_on_step -pearl_ENTITY.on_step = pearl_on_step -flying_bobber_ENTITY.on_step = flying_bobber_on_step - -minetest.register_entity("mcl_throwing:snowball_entity", snowball_ENTITY) -minetest.register_entity("mcl_throwing:egg_entity", egg_ENTITY) -minetest.register_entity("mcl_throwing:ender_pearl_entity", pearl_ENTITY) -minetest.register_entity("mcl_throwing:flying_bobber_entity", flying_bobber_ENTITY) - -local how_to_throw = S("Use the punch key to throw.") - --- Snowball -minetest.register_craftitem("mcl_throwing:snowball", { - description = S("Snowball"), - _tt_help = S("Throwable"), - _doc_items_longdesc = S("Snowballs can be thrown or launched from a dispenser for fun. Hitting something with a snowball does nothing."), - _doc_items_usagehelp = how_to_throw, - inventory_image = "mcl_throwing_snowball.png", - stack_max = 16, - groups = { weapon_ranged = 1 }, - on_use = player_throw_function("mcl_throwing:snowball_entity"), - _on_dispense = dispense_function, -}) - --- Egg -minetest.register_craftitem("mcl_throwing:egg", { - description = S("Egg"), - _tt_help = S("Throwable").."\n"..S("Chance to hatch chicks when broken"), - _doc_items_longdesc = S("Eggs can be thrown or launched from a dispenser and breaks on impact. There is a small chance that 1 or even 4 chicks will pop out of the egg."), - _doc_items_usagehelp = how_to_throw, - inventory_image = "mcl_throwing_egg.png", - stack_max = 16, - on_use = player_throw_function("mcl_throwing:egg_entity"), - _on_dispense = dispense_function, - groups = { craftitem = 1 }, -}) - --- Ender Pearl -minetest.register_craftitem("mcl_throwing:ender_pearl", { - description = S("Ender Pearl"), - _tt_help = S("Throwable").."\n"..minetest.colorize("#FFFF00", S("Teleports you on impact for cost of 5 HP")), - _doc_items_longdesc = S("An ender pearl is an item which can be used for teleportation at the cost of health. It can be thrown and teleport the thrower to its impact location when it hits a solid block or a plant. Each teleportation hurts the user by 5 hit points."), - _doc_items_usagehelp = how_to_throw, - wield_image = "mcl_throwing_ender_pearl.png", - inventory_image = "mcl_throwing_ender_pearl.png", - stack_max = 16, - on_use = player_throw_function("mcl_throwing:ender_pearl_entity"), - groups = { transport = 1 }, -}) - +dofile(modpath.."/register.lua") \ No newline at end of file diff --git a/mods/ITEMS/mcl_throwing/mod.conf b/mods/ITEMS/mcl_throwing/mod.conf index 4bfc2efb51..60d3e31a79 100644 --- a/mods/ITEMS/mcl_throwing/mod.conf +++ b/mods/ITEMS/mcl_throwing/mod.conf @@ -1,3 +1,3 @@ name = mcl_throwing -depends = mcl_fishing +depends = mcl_colors optional_depends = mcl_core, mcl_mobitems, doc diff --git a/mods/ITEMS/mcl_throwing/register.lua b/mods/ITEMS/mcl_throwing/register.lua new file mode 100644 index 0000000000..eace01612d --- /dev/null +++ b/mods/ITEMS/mcl_throwing/register.lua @@ -0,0 +1,335 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +-- The snowball entity +local snowball_ENTITY={ + physical = false, + timer=0, + textures = {"mcl_throwing_snowball.png"}, + visual_size = {x=0.5, y=0.5}, + collisionbox = {0,0,0,0,0,0}, + pointable = false, + + get_staticdata = get_staticdata, + on_activate = on_activate, + _thrower = nil, + + _lastpos={}, +} +local egg_ENTITY={ + physical = false, + timer=0, + textures = {"mcl_throwing_egg.png"}, + visual_size = {x=0.45, y=0.45}, + collisionbox = {0,0,0,0,0,0}, + pointable = false, + + get_staticdata = get_staticdata, + on_activate = on_activate, + _thrower = nil, + + _lastpos={}, +} +-- Ender pearl entity +local pearl_ENTITY={ + physical = false, + timer=0, + textures = {"mcl_throwing_ender_pearl.png"}, + visual_size = {x=0.9, y=0.9}, + collisionbox = {0,0,0,0,0,0}, + pointable = false, + + get_staticdata = get_staticdata, + on_activate = on_activate, + + _lastpos={}, + _thrower = nil, -- Player ObjectRef of the player who threw the ender pearl +} + +local check_object_hit = function(self, pos, dmg) + for _,object in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do + + local entity = object:get_luaentity() + + if entity + and entity.name ~= self.object:get_luaentity().name then + + if object:is_player() and self._thrower ~= object:get_player_name() then + -- TODO: Deal knockback + self.object:remove() + return true + elseif (entity._cmi_is_mob == true or entity._hittable_by_projectile) and (self._thrower ~= object) then + -- FIXME: Knockback is broken + object:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = dmg, + }, nil) + return true + end + end + end + return false +end + +local snowball_particles = function(pos, vel) + local vel = vector.normalize(vector.multiply(vel, -1)) + minetest.add_particlespawner({ + amount = 20, + time = 0.001, + minpos = pos, + maxpos = pos, + minvel = vector.add({x=-2, y=3, z=-2}, vel), + maxvel = vector.add({x=2, y=5, z=2}, vel), + minacc = {x=0, y=-9.81, z=0}, + maxacc = {x=0, y=-9.81, z=0}, + minexptime = 1, + maxexptime = 3, + minsize = 0.7, + maxsize = 0.7, + collisiondetection = true, + collision_removal = true, + object_collision = false, + texture = "weather_pack_snow_snowflake"..math.random(1,2)..".png", + }) +end + +-- Snowball on_step()--> called when snowball is moving. +local snowball_on_step = function(self, dtime) + self.timer=self.timer+dtime + local pos = self.object:get_pos() + local vel = self.object:get_velocity() + local node = minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] + + + -- Destroy when hitting a solid node + if self._lastpos.x~=nil then + if (def and def.walkable) or not def then + minetest.sound_play("mcl_throwing_snowball_impact_hard", { pos = pos, max_hear_distance=16, gain=0.7 }, true) + snowball_particles(self._lastpos, vel) + self.object:remove() + return + end + end + + if check_object_hit(self, pos, {snowball_vulnerable = 3}) then + minetest.sound_play("mcl_throwing_snowball_impact_soft", { pos = pos, max_hear_distance=16, gain=0.7 }, true) + snowball_particles(pos, vel) + self.object:remove() + return + end + + self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set _lastpos-->Node will be added at last pos outside the node +end + +-- Movement function of egg +local egg_on_step = function(self, dtime) + self.timer=self.timer+dtime + local pos = self.object:get_pos() + local node = minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] + + -- Destroy when hitting a solid node with chance to spawn chicks + if self._lastpos.x~=nil then + if (def and def.walkable) or not def then + -- 1/8 chance to spawn a chick + -- FIXME: Chicks have a quite good chance to spawn in walls + local r = math.random(1,8) + + -- Turn given object into a child + local make_child= function(object) + local ent = object:get_luaentity() + object:set_properties({ + visual_size = { x = ent.base_size.x/2, y = ent.base_size.y/2 }, + collisionbox = { + ent.base_colbox[1]/2, + ent.base_colbox[2]/2, + ent.base_colbox[3]/2, + ent.base_colbox[4]/2, + ent.base_colbox[5]/2, + ent.base_colbox[6]/2, + } + }) + ent.child = true + end + if r == 1 then + make_child(minetest.add_entity(self._lastpos, "mobs_mc:chicken")) + + -- BONUS ROUND: 1/32 chance to spawn 3 additional chicks + local r = math.random(1,32) + if r == 1 then + local offsets = { + { x=0.7, y=0, z=0 }, + { x=-0.7, y=0, z=-0.7 }, + { x=-0.7, y=0, z=0.7 }, + } + for o=1, 3 do + local pos = vector.add(self._lastpos, offsets[o]) + make_child(minetest.add_entity(pos, "mobs_mc:chicken")) + end + end + end + minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true) + self.object:remove() + return + end + end + + -- Destroy when hitting a mob or player (no chick spawning) + if check_object_hit(self, pos) then + minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true) + self.object:remove() + return + end + + self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node +end + +-- Movement function of ender pearl +local pearl_on_step = function(self, dtime) + self.timer=self.timer+dtime + local pos = self.object:get_pos() + pos.y = math.floor(pos.y) + local node = minetest.get_node(pos) + local nn = node.name + local def = minetest.registered_nodes[node.name] + + -- Destroy when hitting a solid node + if self._lastpos.x~=nil then + local walkable = (def and def.walkable) + + -- No teleport for hitting ignore for now. Otherwise the player could get stuck. + -- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas + if node.name == "ignore" then + self.object:remove() + -- Activate when hitting a solid node or a plant + elseif walkable or nn == "mcl_core:vine" or nn == "mcl_core:deadbush" or minetest.get_item_group(nn, "flower") ~= 0 or minetest.get_item_group(nn, "sapling") ~= 0 or minetest.get_item_group(nn, "plant") ~= 0 or minetest.get_item_group(nn, "mushroom") ~= 0 or not def then + local player = minetest.get_player_by_name(self._thrower) + if player then + -- Teleport and hurt player + + -- First determine good teleport position + local dir = {x=0, y=0, z=0} + + local v = self.object:get_velocity() + if walkable then + local vc = table.copy(v) -- vector for calculating + -- Node is walkable, we have to find a place somewhere outside of that node + vc = vector.normalize(vc) + + -- Zero-out the two axes with a lower absolute value than + -- the axis with the strongest force + local lv, ld + lv, ld = math.abs(vc.y), "y" + if math.abs(vc.x) > lv then + lv, ld = math.abs(vc.x), "x" + end + if math.abs(vc.z) > lv then + lv, ld = math.abs(vc.z), "z" + end + if ld ~= "x" then vc.x = 0 end + if ld ~= "y" then vc.y = 0 end + if ld ~= "z" then vc.z = 0 end + + -- Final tweaks to the teleporting pos, based on direction + -- Impact from the side + dir.x = vc.x * -1 + dir.z = vc.z * -1 + + -- Special case: top or bottom of node + if vc.y > 0 then + -- We need more space when impact is from below + dir.y = -2.3 + elseif vc.y < 0 then + -- Standing on top + dir.y = 0.5 + end + end + -- If node was not walkable, no modification to pos is made. + + -- Final teleportation position + local telepos = vector.add(pos, dir) + local telenode = minetest.get_node(telepos) + + --[[ It may be possible that telepos is walkable due to the algorithm. + Especially when the ender pearl is faster horizontally than vertical. + This applies final fixing, just to be sure we're not in a walkable node ]] + if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then + if v.y < 0 then + telepos.y = telepos.y + 0.5 + else + telepos.y = telepos.y - 2.3 + end + end + + local oldpos = player:get_pos() + -- Teleport and hurt player + player:set_pos(telepos) + player:set_hp(player:get_hp() - 5, { type = "fall", from = "mod" }) + + -- 5% chance to spawn endermite at the player's origin + local r = math.random(1,20) + if r == 1 then + minetest.add_entity(oldpos, "mobs_mc:endermite") + end + + end + self.object:remove() + return + end + end + self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node +end + +snowball_ENTITY.on_step = snowball_on_step +egg_ENTITY.on_step = egg_on_step +pearl_ENTITY.on_step = pearl_on_step + +minetest.register_entity("mcl_throwing:snowball_entity", snowball_ENTITY) +minetest.register_entity("mcl_throwing:egg_entity", egg_ENTITY) +minetest.register_entity("mcl_throwing:ender_pearl_entity", pearl_ENTITY) + + +local how_to_throw = S("Use the punch key to throw.") + +-- Snowball +minetest.register_craftitem("mcl_throwing:snowball", { + description = S("Snowball"), + _tt_help = S("Throwable"), + _doc_items_longdesc = S("Snowballs can be thrown or launched from a dispenser for fun. Hitting something with a snowball does nothing."), + _doc_items_usagehelp = how_to_throw, + inventory_image = "mcl_throwing_snowball.png", + stack_max = 16, + groups = { weapon_ranged = 1 }, + on_use = mcl_throwing.get_player_throw_function("mcl_throwing:snowball_entity"), + _on_dispense = mcl_throwing.dispense_function, +}) + +-- Egg +minetest.register_craftitem("mcl_throwing:egg", { + description = S("Egg"), + _tt_help = S("Throwable").."\n"..S("Chance to hatch chicks when broken"), + _doc_items_longdesc = S("Eggs can be thrown or launched from a dispenser and breaks on impact. There is a small chance that 1 or even 4 chicks will pop out of the egg."), + _doc_items_usagehelp = how_to_throw, + inventory_image = "mcl_throwing_egg.png", + stack_max = 16, + on_use = mcl_throwing.get_player_throw_function("mcl_throwing:egg_entity"), + _on_dispense = mcl_throwing.dispense_function, + groups = { craftitem = 1 }, +}) + +-- Ender Pearl +minetest.register_craftitem("mcl_throwing:ender_pearl", { + description = S("Ender Pearl"), + _tt_help = S("Throwable").."\n"..minetest.colorize("#FFFF00", S("Teleports you on impact for cost of 5 HP")), + _doc_items_longdesc = S("An ender pearl is an item which can be used for teleportation at the cost of health. It can be thrown and teleport the thrower to its impact location when it hits a solid block or a plant. Each teleportation hurts the user by 5 hit points."), + _doc_items_usagehelp = how_to_throw, + wield_image = "mcl_throwing_ender_pearl.png", + inventory_image = "mcl_throwing_ender_pearl.png", + stack_max = 16, + on_use = mcl_throwing.get_player_throw_function("mcl_throwing:ender_pearl_entity"), + groups = { transport = 1 }, +}) + +mcl_throwing.register_throwable_object("mcl_throwing:snowball", "mcl_throwing:snowball_entity", 22) +mcl_throwing.register_throwable_object("mcl_throwing:egg", "mcl_throwing:egg_entity", 22) +mcl_throwing.register_throwable_object("mcl_throwing:ender_pearl", "mcl_throwing:ender_pearl_entity", 22) From e11941c107fb9418ed91c23dcced84fd1853c249 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 22:43:18 +0100 Subject: [PATCH 030/234] Add API documentation for mcl_throwing --- mods/ITEMS/mcl_throwing/API.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_throwing/API.md b/mods/ITEMS/mcl_throwing/API.md index a75a71635e..f2b1c73741 100644 --- a/mods/ITEMS/mcl_throwing/API.md +++ b/mods/ITEMS/mcl_throwing/API.md @@ -1,3 +1,35 @@ # mcl_throwing -## mcl_throwing.throw(throw_item, pos, dir, velocity, thrower) \ No newline at end of file +## mcl_throwing.throw(throw_item, pos, dir, velocity, thrower) +Throw a throwable item. + +* throw_item: itemstring of the throwable item +* pos: initial position of the entity +* dir: direction where the throwable item will be thrown +* velocity: (optional) will overide the default velocity value (can be nil) +* thrower: (optional) player/entity who throw the object (can be nil) + +## mcl_throwing.register_throwable_object(name, entity, velocity) +Register a throwable item. + +* name: itemname of the throwable object +* entity: entity thrown +* velocity: initial velocity of the entity + +## mcl_throwing.dispense_function(stack, dispenserpos, droppos, dropnode, dropdir) +Throw throwable item from dispencer. + +Shouldn't be called directly. + +Must be used in item definition: + +`_on_dispense = mcl_throwing.dispense_function,` + +## mcl_throwing.get_player_throw_function(entity_name, velocity) + +Return a function who handle item throwing (to be used in item definition) + +Handle creative mode, and throw params. + +* entity_name: the name of the entity to throw +* velocity: (optional) velocity overide (can be nil) From e2adead7003f43fba70a9ea6522030bf64ec2106 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 26 Mar 2021 22:50:37 +0100 Subject: [PATCH 031/234] use proper colors --- mods/ITEMS/mcl_fishing/init.lua | 2 +- mods/ITEMS/mcl_fishing/mod.conf | 2 +- mods/ITEMS/mcl_throwing/register.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index d431ee10c9..228d490ea6 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -495,7 +495,7 @@ minetest.register_craftitem("mcl_fishing:clownfish_raw", { minetest.register_craftitem("mcl_fishing:pufferfish_raw", { description = S("Pufferfish"), - _tt_help = minetest.colorize("#FFFF00", S("Very poisonous")), + _tt_help = minetest.colorize(mcl_colors.YELLOW, S("Very poisonous")), _doc_items_longdesc = S("Pufferfish are a common species of fish and can be obtained by fishing. They can technically be eaten, but they are very bad for humans. Eating a pufferfish only restores 1 hunger point and will poison you very badly (which drains your health non-fatally) and causes serious food poisoning (which increases your hunger)."), inventory_image = "mcl_fishing_pufferfish_raw.png", on_place = minetest.item_eat(1), diff --git a/mods/ITEMS/mcl_fishing/mod.conf b/mods/ITEMS/mcl_fishing/mod.conf index 65c2f68a9f..c4e5f5f2e7 100644 --- a/mods/ITEMS/mcl_fishing/mod.conf +++ b/mods/ITEMS/mcl_fishing/mod.conf @@ -1,3 +1,3 @@ name = mcl_fishing description = Adds fish and fishing poles to go fishing. -depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting, mcl_throwing +depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting, mcl_throwing, mcl_colors diff --git a/mods/ITEMS/mcl_throwing/register.lua b/mods/ITEMS/mcl_throwing/register.lua index eace01612d..027ff4e938 100644 --- a/mods/ITEMS/mcl_throwing/register.lua +++ b/mods/ITEMS/mcl_throwing/register.lua @@ -320,7 +320,7 @@ minetest.register_craftitem("mcl_throwing:egg", { -- Ender Pearl minetest.register_craftitem("mcl_throwing:ender_pearl", { description = S("Ender Pearl"), - _tt_help = S("Throwable").."\n"..minetest.colorize("#FFFF00", S("Teleports you on impact for cost of 5 HP")), + _tt_help = S("Throwable").."\n"..minetest.colorize(mcl_colors.YELLOW, S("Teleports you on impact for cost of 5 HP")), _doc_items_longdesc = S("An ender pearl is an item which can be used for teleportation at the cost of health. It can be thrown and teleport the thrower to its impact location when it hits a solid block or a plant. Each teleportation hurts the user by 5 hit points."), _doc_items_usagehelp = how_to_throw, wield_image = "mcl_throwing_ender_pearl.png", From e2fd0823b95af552c34d15af6a7d362e31649803 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 07:10:50 +0100 Subject: [PATCH 032/234] Fix #1398 --- mods/ITEMS/mcl_anvils/init.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index 4495fb6189..c3c238e7f9 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -488,7 +488,6 @@ S("The anvil has limited durability and 3 damage levels: undamaged, slightly dam local anvildef1 = table.copy(anvildef) anvildef1.description = S("Slightly Damaged Anvil") anvildef1._doc_items_create_entry = false -anvildef1.groups.not_in_creative_inventory = 1 anvildef1.groups.anvil = 2 anvildef1._doc_items_create_entry = false anvildef1.tiles = {"mcl_anvils_anvil_top_damaged_1.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"} @@ -496,7 +495,6 @@ anvildef1.tiles = {"mcl_anvils_anvil_top_damaged_1.png^[transformR90", "mcl_anvi local anvildef2 = table.copy(anvildef) anvildef2.description = S("Very Damaged Anvil") anvildef2._doc_items_create_entry = false -anvildef2.groups.not_in_creative_inventory = 1 anvildef2.groups.anvil = 3 anvildef2._doc_items_create_entry = false anvildef2.tiles = {"mcl_anvils_anvil_top_damaged_2.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"} From 61c9d065fb4c4836f930c8587ef378603c7a43cb Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 07:19:35 +0100 Subject: [PATCH 033/234] =?UTF-8?q?Fix=20=C2=A0#1400?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/ITEMS/mcl_end/eye_of_ender.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_end/eye_of_ender.lua b/mods/ITEMS/mcl_end/eye_of_ender.lua index 16f1c906bb..afac9ebfc2 100644 --- a/mods/ITEMS/mcl_end/eye_of_ender.lua +++ b/mods/ITEMS/mcl_end/eye_of_ender.lua @@ -29,7 +29,7 @@ minetest.register_entity("mcl_end:ender_eye", { if self._age >= 3 then -- End of life local r = math.random(1,5) - if r == 1 or minetest.is_creative_enabled("") then + if r == 1 then -- 20% chance to get destroyed completely. -- 100% if in Creative Mode self.object:remove() From 9bb5e748b9443e03b76262c693d1d38fa6500d16 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 15:20:01 +0100 Subject: [PATCH 034/234] Add documentation to mcl_crafting_table API --- mods/ITEMS/mcl_crafting_table/API.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 mods/ITEMS/mcl_crafting_table/API.md diff --git a/mods/ITEMS/mcl_crafting_table/API.md b/mods/ITEMS/mcl_crafting_table/API.md new file mode 100644 index 0000000000..45aa0c9cea --- /dev/null +++ b/mods/ITEMS/mcl_crafting_table/API.md @@ -0,0 +1,6 @@ +# mcl_crafting_table +Add a node which allow players to craft more complex things. + +## mcl_crafting_table.show_crafting_form(player) +Show the crafting form to a player. +Used in the node registration, but can be used by external mods. \ No newline at end of file From cb294a5cadc77fe4da3495389a05aa5fed7023af Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 15:27:34 +0100 Subject: [PATCH 035/234] Add documentation to mcl_wip (pretty useless...) --- mods/MISC/mcl_wip/API.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 mods/MISC/mcl_wip/API.md diff --git a/mods/MISC/mcl_wip/API.md b/mods/MISC/mcl_wip/API.md new file mode 100644 index 0000000000..e3439af775 --- /dev/null +++ b/mods/MISC/mcl_wip/API.md @@ -0,0 +1,16 @@ +# mcl_wip +Used to mark items or nodes as WIP. + +## mcl_wip.register_wip_item(itemname) +Register as a WIP item. +If isn't a valid itemname, an error will be shown after mods loaded. + +## mcl_wip.register_experimental_item(itemname) +Register as a experimental item. +If isn't a valid itemname, an error will be shown after mods loaded. + +## mcl_wip.registered_wip_items +Table containing WIP items names. + +## mcl_wip.registered_experimental_items +Table containing experimental items names. \ No newline at end of file From 30e50a64ef6ffcad961321ea1dc3cb07e51f640f Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 20:12:48 +0100 Subject: [PATCH 036/234] basic API (WIP) --- mods/PLAYER/mcl_death_drop/API.md | 12 ++++++++++ mods/PLAYER/mcl_death_drop/init.lua | 34 +++++++++++++++++++---------- 2 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 mods/PLAYER/mcl_death_drop/API.md diff --git a/mods/PLAYER/mcl_death_drop/API.md b/mods/PLAYER/mcl_death_drop/API.md new file mode 100644 index 0000000000..6f1d1cde74 --- /dev/null +++ b/mods/PLAYER/mcl_death_drop/API.md @@ -0,0 +1,12 @@ +# mcl_death_drop +Drop registered inventories on player death. + +## mcl_death_drop.register_dropped_list(inv, listname, drop) +* inv: string of function returning a string +* listname: string +* drop: bool +-- if true the entire list will be dropped +-- if false, items with curse_of_vanishing enchantement will be broken. + +## mcl_death_drop.registered_dropped_lists +Table containing dropped list definition. \ No newline at end of file diff --git a/mods/PLAYER/mcl_death_drop/init.lua b/mods/PLAYER/mcl_death_drop/init.lua index 56e6ea5227..6c51618a1e 100644 --- a/mods/PLAYER/mcl_death_drop/init.lua +++ b/mods/PLAYER/mcl_death_drop/init.lua @@ -1,3 +1,18 @@ +local random = math.random + +mcl_death_drop = {} + +mcl_death_drop.registered_dropped_lists = {} + +function mcl_death_drop.register_dropped_list(inv, listname, drop) + table.insert(mcl_death_drop.registered_dropped_player_lists, {inv=inv, listname=listname, drop=drop}) +end + +mcl_death_drop.register_dropped_list("PLAYER", "main", true) +mcl_death_drop.register_dropped_list("PLAYER", "craft", true) +mcl_death_drop.register_dropped_list("PLAYER", "armor", true) +mcl_death_drop.register_dropped_list(function(player) return minetest.get_inventory({type="detached", name=player:get_player_name().."_armor"}) end , "armor", false) + minetest.register_on_dieplayer(function(player) local keep = minetest.settings:get_bool("mcl_keepInventory", false) if keep == false then @@ -7,20 +22,15 @@ minetest.register_on_dieplayer(function(player) local name, player_armor_inv, armor_armor_inv, pos = armor:get_valid_player(player, "[on_dieplayer]") -- No item drop if in deep void local void, void_deadly = mcl_worlds.is_in_void(pos) - local lists = { - { inv = inv, listname = "main", drop = true }, - { inv = inv, listname = "craft", drop = true }, - { inv = player_armor_inv, listname = "armor", drop = true }, - { inv = armor_armor_inv, listname = "armor", drop = false }, - } - for l=1,#lists do - local inv = lists[l].inv - local listname = lists[l].listname - local drop = lists[l].drop + + for l=1,#mcl_death_drop.registered_dropped_lists do + local inv = mcl_death_drop.registered_dropped_lists[l].inv + local listname = mcl_death_drop.registered_dropped_lists[l].listname + local drop = mcl_death_drop.registered_dropped_lists[l].drop if inv ~= nil then for i, stack in ipairs(inv:get_list(listname)) do - local x = math.random(0, 9)/3 - local z = math.random(0, 9)/3 + local x = random(0, 9)/3 + local z = random(0, 9)/3 pos.x = pos.x + x pos.z = pos.z + z if not void_deadly and drop and not mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then From 6a6b5970b351ca96ea12baf026055940b8880570 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 20:23:51 +0100 Subject: [PATCH 037/234] fix API --- mods/PLAYER/mcl_death_drop/init.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mods/PLAYER/mcl_death_drop/init.lua b/mods/PLAYER/mcl_death_drop/init.lua index 6c51618a1e..693b21cd84 100644 --- a/mods/PLAYER/mcl_death_drop/init.lua +++ b/mods/PLAYER/mcl_death_drop/init.lua @@ -5,7 +5,7 @@ mcl_death_drop = {} mcl_death_drop.registered_dropped_lists = {} function mcl_death_drop.register_dropped_list(inv, listname, drop) - table.insert(mcl_death_drop.registered_dropped_player_lists, {inv=inv, listname=listname, drop=drop}) + table.insert(mcl_death_drop.registered_dropped_lists, {inv=inv, listname=listname, drop=drop}) end mcl_death_drop.register_dropped_list("PLAYER", "main", true) @@ -17,7 +17,7 @@ minetest.register_on_dieplayer(function(player) local keep = minetest.settings:get_bool("mcl_keepInventory", false) if keep == false then -- Drop inventory, crafting grid and armor - local inv = player:get_inventory() + local playerinv = player:get_inventory() local pos = player:get_pos() local name, player_armor_inv, armor_armor_inv, pos = armor:get_valid_player(player, "[on_dieplayer]") -- No item drop if in deep void @@ -25,6 +25,11 @@ minetest.register_on_dieplayer(function(player) for l=1,#mcl_death_drop.registered_dropped_lists do local inv = mcl_death_drop.registered_dropped_lists[l].inv + if inv == "PLAYER" then + inv = playerinv + elseif type(inv) == "function" then + inv = inv(player) + end local listname = mcl_death_drop.registered_dropped_lists[l].listname local drop = mcl_death_drop.registered_dropped_lists[l].drop if inv ~= nil then From 3ba7a402513faf9585e2a0018003608abd6759f6 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 23:07:46 +0100 Subject: [PATCH 038/234] Add API documentation --- mods/ITEMS/mcl_buckets/API.md | 20 ++++++++++---------- mods/PLAYER/mcl_death_drop/API.md | 10 ++++++---- mods/PLAYER/mcl_death_drop/init.lua | 3 +-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/API.md b/mods/ITEMS/mcl_buckets/API.md index 69ee4b21da..53f7d36989 100644 --- a/mods/ITEMS/mcl_buckets/API.md +++ b/mods/ITEMS/mcl_buckets/API.md @@ -5,17 +5,17 @@ Add an API to register buckets to mcl Register a new liquid Accept folowing params: -* source_place = a string or function. +* source_place: a string or function. * string: name of the node to place * function(pos): will returns name of the node to place with pos being the placement position -* source_take = table of liquid source node names to take -* itemname = itemstring of the new bucket item (or nil if liquid is not takeable) -* inventory_image = texture of the new bucket item (ignored if itemname == nil) -* name = user-visible bucket description -* longdesc = long explanatory description (for help) -* usagehelp = short usage explanation (for help) -* tt_help = very short tooltip help -* extra_check(pos, placer) = optional function(pos) which can returns false to avoid placing the liquid. Placer is object/player who is placing the liquid, can be nil. -* groups = optional list of item groups +* source_take: table of liquid source node names to take +* itemname: itemstring of the new bucket item (or nil if liquid is not takeable) +* inventory_image: texture of the new bucket item (ignored if itemname == nil) +* name: user-visible bucket description +* longdesc: long explanatory description (for help) +* usagehelp: short usage explanation (for help) +* tt_help: very short tooltip help +* extra_check(pos, placer): (optional) function(pos) which can returns false to avoid placing the liquid. Placer is object/player who is placing the liquid, can be nil. +* groups: optional list of item groups This function can be called from any mod (which depends on this one) \ No newline at end of file diff --git a/mods/PLAYER/mcl_death_drop/API.md b/mods/PLAYER/mcl_death_drop/API.md index 6f1d1cde74..70fbd14993 100644 --- a/mods/PLAYER/mcl_death_drop/API.md +++ b/mods/PLAYER/mcl_death_drop/API.md @@ -2,11 +2,13 @@ Drop registered inventories on player death. ## mcl_death_drop.register_dropped_list(inv, listname, drop) -* inv: string of function returning a string +* inv: can be: + * "PLAYER": player inventory (to avoid multiple calling to get_inventory()) + * function: must return inventory * listname: string * drop: bool --- if true the entire list will be dropped --- if false, items with curse_of_vanishing enchantement will be broken. + * true: the entire list will be dropped + * false: items with curse_of_vanishing enchantement will be broken. ## mcl_death_drop.registered_dropped_lists -Table containing dropped list definition. \ No newline at end of file +Table containing dropped list inventory, name and drop state. \ No newline at end of file diff --git a/mods/PLAYER/mcl_death_drop/init.lua b/mods/PLAYER/mcl_death_drop/init.lua index 693b21cd84..7c54334a95 100644 --- a/mods/PLAYER/mcl_death_drop/init.lua +++ b/mods/PLAYER/mcl_death_drop/init.lua @@ -11,7 +11,7 @@ end mcl_death_drop.register_dropped_list("PLAYER", "main", true) mcl_death_drop.register_dropped_list("PLAYER", "craft", true) mcl_death_drop.register_dropped_list("PLAYER", "armor", true) -mcl_death_drop.register_dropped_list(function(player) return minetest.get_inventory({type="detached", name=player:get_player_name().."_armor"}) end , "armor", false) +mcl_death_drop.register_dropped_list(function(player) return select(3, armor:get_valid_player(player)) end , "armor", false) minetest.register_on_dieplayer(function(player) local keep = minetest.settings:get_bool("mcl_keepInventory", false) @@ -19,7 +19,6 @@ minetest.register_on_dieplayer(function(player) -- Drop inventory, crafting grid and armor local playerinv = player:get_inventory() local pos = player:get_pos() - local name, player_armor_inv, armor_armor_inv, pos = armor:get_valid_player(player, "[on_dieplayer]") -- No item drop if in deep void local void, void_deadly = mcl_worlds.is_in_void(pos) From 57ce5143b9ee0fe0fe8b422521a9deb38ed36928 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 27 Mar 2021 23:39:22 +0100 Subject: [PATCH 039/234] Clarify API documentation --- mods/PLAYER/mcl_death_drop/API.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/PLAYER/mcl_death_drop/API.md b/mods/PLAYER/mcl_death_drop/API.md index 70fbd14993..b19e2fd7c8 100644 --- a/mods/PLAYER/mcl_death_drop/API.md +++ b/mods/PLAYER/mcl_death_drop/API.md @@ -3,8 +3,8 @@ Drop registered inventories on player death. ## mcl_death_drop.register_dropped_list(inv, listname, drop) * inv: can be: - * "PLAYER": player inventory (to avoid multiple calling to get_inventory()) - * function: must return inventory + * "PLAYER": will be interpreted like player inventory (to avoid multiple calling to get_inventory()) + * function(player): must return inventory * listname: string * drop: bool * true: the entire list will be dropped From ce123d4676e5aabf6a878509dc7f933b346a2b22 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:02:35 +0100 Subject: [PATCH 040/234] add API documentation to mcl_autogroup --- mods/CORE/mcl_autogroup/API.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 mods/CORE/mcl_autogroup/API.md diff --git a/mods/CORE/mcl_autogroup/API.md b/mods/CORE/mcl_autogroup/API.md new file mode 100644 index 0000000000..79b9770b5d --- /dev/null +++ b/mods/CORE/mcl_autogroup/API.md @@ -0,0 +1,27 @@ +# mcl_autogroup +This mod emulate digging times from mc. + +## mcl_autogroup.can_harvest(nodename, toolname) +Return true if can be dig with . +* nodename: string, valid nodename +* toolname: (optional) string, valid toolname + +## mcl_autogroup.get_groupcaps(toolname, efficiency) +This function is used to calculate diggroups for tools. +WARNING: This function can only be called after mod initialization. +* toolname: string, name of the tool being enchanted (like "mcl_tools:diamond_pickaxe") +* efficiency: (optional) integer, the efficiency level the tool is enchanted with (default 0) + +## mcl_autogroup.get_wear(toolname, diggroup) +Return the max wear of with +WARNING: This function can only be called after mod initialization. +* toolname: string, name of the tool used +* diggroup: string, the name of the diggroup the tool is used on + +## mcl_autogroup.register_diggroup(group, def) +* group: string, name of the group to register as a digging group +* def: (optional) table, table with information about the diggroup (defaults to {} if unspecified) + * level: (optional) string, if specified it is an array containing the names of the different digging levels the digging group supports + +## mcl_autogroup.registered_diggroups +List of registered diggroups, indexed by name. \ No newline at end of file From fb50b256ed6c2e0451e950c33114c51507c08618 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:12:41 +0100 Subject: [PATCH 041/234] add API documentation to flowlib (part 1) --- mods/CORE/flowlib/API.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 mods/CORE/flowlib/API.md diff --git a/mods/CORE/flowlib/API.md b/mods/CORE/flowlib/API.md new file mode 100644 index 0000000000..d9f54e4bd0 --- /dev/null +++ b/mods/CORE/flowlib/API.md @@ -0,0 +1,35 @@ +# flowlib +Simple flow functions. + +## flowlib.is_touching() + + +## flowlib.is_water(pos) +Return true if node at is water, false overwise. +* pos: position + +## flowlib.node_is_water(node) +Return true if is water, false overwise. +* node: node + +## flowlib.is_lava(pos) +Return true if node at is lava, false overwise. +* pos: position + +## flowlib.node_is_lava(node) +Return true if is lava, false overwise. +* node: node + +## flowlib.is_liquid(pos) +Return true if node at is liquid, false overwise. +* pos: position + +## flowlib.node_is_liquid(node) +Return true if is liquid, false overwise. +* node: node + +## flowlib.quick_flow(pos, node) +* pos: position +* node: node + +## flowlib.move_centre(pos, realpos, node, radius) \ No newline at end of file From 19db2a479f702a9fa1f2fb44e6b4253c5e27a9e7 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:18:19 +0100 Subject: [PATCH 042/234] add API documentation to flowlib (part 2) --- mods/CORE/flowlib/API.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mods/CORE/flowlib/API.md b/mods/CORE/flowlib/API.md index d9f54e4bd0..7ebb4cc87d 100644 --- a/mods/CORE/flowlib/API.md +++ b/mods/CORE/flowlib/API.md @@ -1,7 +1,11 @@ # flowlib Simple flow functions. -## flowlib.is_touching() +## flowlib.is_touching(realpos, nodepos, radius) +Return true if a sphere of at collide with node at . +* realpos: position +* nodepos: position +* radius: number ## flowlib.is_water(pos) From 2a5dcd1634c8d546636b7725308efd3705f1e0f9 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:23:57 +0100 Subject: [PATCH 043/234] add API documentation to flowlib (part 3) --- mods/CORE/flowlib/API.md | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/CORE/flowlib/API.md b/mods/CORE/flowlib/API.md index 7ebb4cc87d..0542e45190 100644 --- a/mods/CORE/flowlib/API.md +++ b/mods/CORE/flowlib/API.md @@ -33,6 +33,7 @@ Return true if is liquid, false overwise. * node: node ## flowlib.quick_flow(pos, node) +Return direction where the water is flowing (to be use to push mobs, items...). * pos: position * node: node From 39ac3f208d003f77ad3fcec1a79d6b1c4e4799a3 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:25:54 +0100 Subject: [PATCH 044/234] add API documentation to flowlib (part 4) --- mods/CORE/flowlib/API.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mods/CORE/flowlib/API.md b/mods/CORE/flowlib/API.md index 0542e45190..f3282c9752 100644 --- a/mods/CORE/flowlib/API.md +++ b/mods/CORE/flowlib/API.md @@ -37,4 +37,8 @@ Return direction where the water is flowing (to be use to push mobs, items...). * pos: position * node: node -## flowlib.move_centre(pos, realpos, node, radius) \ No newline at end of file +## flowlib.move_centre(pos, realpos, node, radius) +* pos: position +* realpos: position +* node: node +* radius: number \ No newline at end of file From 52939ff6a409e777106b82d87c34d917cb0c9fd4 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:32:52 +0100 Subject: [PATCH 045/234] add API documentation to flowlib (part 5) --- mods/CORE/flowlib/API.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/CORE/flowlib/API.md b/mods/CORE/flowlib/API.md index f3282c9752..20e85036b9 100644 --- a/mods/CORE/flowlib/API.md +++ b/mods/CORE/flowlib/API.md @@ -7,7 +7,6 @@ Return true if a sphere of at collide with node at . * nodepos: position * radius: number - ## flowlib.is_water(pos) Return true if node at is water, false overwise. * pos: position @@ -38,7 +37,9 @@ Return direction where the water is flowing (to be use to push mobs, items...). * node: node ## flowlib.move_centre(pos, realpos, node, radius) +Return the pos of the nearest not water block near from in a sphere of at . +WARNING: This function is never used in mcl2, use at your own risk. The informations described here may be wrong. * pos: position -* realpos: position +* realpos: position, position of the entity * node: node * radius: number \ No newline at end of file From e56d9d2ab805250221ab0d3fed54bac3f8e03444 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:44:36 +0100 Subject: [PATCH 046/234] add API documentation to controls --- mods/CORE/controls/API.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 mods/CORE/controls/API.md diff --git a/mods/CORE/controls/API.md b/mods/CORE/controls/API.md new file mode 100644 index 0000000000..8d9df6ca50 --- /dev/null +++ b/mods/CORE/controls/API.md @@ -0,0 +1,23 @@ +# controls + +## controls.players +Table containing player controls at runtime. +WARNING: Never use this table in writing + +## controls.register_on_press(func) +Register a function that will be executed with (player, keyname) every time a player press a key. + +## controls.registered_on_press +Table containing functions registered with controls.register_on_press(). + +## controls.register_on_release(func) +Register a function that will be executed with (player, keyname, clock_from_last_press) every time a player release a key. + +## controls.registered_on_release +Table containing functions registered with controls.register_on_release(). + +## controls.register_on_hold(func) +Register a function that will be executed with (player, keyname, clock_from_start_hold) every time a player hold a key. + +## controls.registered_on_hold +Table containing functions registered with controls.register_on_hold(). \ No newline at end of file From 6f9c1856b8bae6b7293ead323ab291aa482a0b81 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 00:48:24 +0100 Subject: [PATCH 047/234] add API documentation to mcl_colors (!) --- mods/CORE/mcl_colors/API.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 mods/CORE/mcl_colors/API.md diff --git a/mods/CORE/mcl_colors/API.md b/mods/CORE/mcl_colors/API.md new file mode 100644 index 0000000000..71cad335b1 --- /dev/null +++ b/mods/CORE/mcl_colors/API.md @@ -0,0 +1,8 @@ +# mcl_colors +Mod providing global table containing legacity minecraft colors to be used in mods. + +## mcl_colors.* +Colors by upper name, in hex value. + +## mcl_colors.background.* +Background colors by upper name, in hex value. From cdb67d96a6cf4a72a94b98ff9f0b5055af0cd977 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 01:00:18 +0100 Subject: [PATCH 048/234] add API documentation to mcl_explosions --- mods/CORE/mcl_explosions/API.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 mods/CORE/mcl_explosions/API.md diff --git a/mods/CORE/mcl_explosions/API.md b/mods/CORE/mcl_explosions/API.md new file mode 100644 index 0000000000..cb0e9252d9 --- /dev/null +++ b/mods/CORE/mcl_explosions/API.md @@ -0,0 +1,15 @@ +# mcl_explosions +This mod provide helper functions to create explosions. + +## mcl_explosions.explode(pos, strength, info, puncher) +* pos: position, initial position of the explosion +* strenght: number, radius of the explosion +* info: table, explosion informations: + * drop_chance: number, if specified becomes the drop chance of all nodes in the explosion (default: 1.0 / strength) + * max_blast_resistance: int, if specified the explosion will treat all non-indestructible nodes as having a blast resistance of no more than this value + * sound: bool, if true, the explosion will play a sound (default: true) + * particles: bool, if true, the explosion will create particles (default: true) + * fire: bool, if true, 1/3 nodes become fire (default: false) + * griefing: bool, if true, the explosion will destroy nodes (default: true) + * grief_protected: bool, if true, the explosion will also destroy nodes which have been protected (default: false) +* puncher: (optional) entity, will be used as source for damage done by the explosion \ No newline at end of file From 54e7529754e0c5b1f6b597e7771273e716e3c48a Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 28 Mar 2021 04:32:57 +0400 Subject: [PATCH 049/234] [mcl_achievements] Add mcl:stoneAge, mcl:hotStuff, mcl:obsidian --- mods/HUD/mcl_achievements/init.lua | 17 +++++++++++++++++ mods/ITEMS/mcl_buckets/init.lua | 3 +++ mods/ITEMS/mcl_core/nodes_base.lua | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/mods/HUD/mcl_achievements/init.lua b/mods/HUD/mcl_achievements/init.lua index 7473568d28..2f1db1fe6e 100644 --- a/mods/HUD/mcl_achievements/init.lua +++ b/mods/HUD/mcl_achievements/init.lua @@ -238,3 +238,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) awards.show_to(name, name, nil, false) end end) + + +awards.register_achievement("mcl:stoneAge", { + title = S("Stone Age"), + description = S("Mine a stone with new pickaxe."), + icon = "default_cobble.png", +}) +awards.register_achievement("mcl:hotStuff", { + title = S("Hot Stuff"), + description = S("Put lava in a bucket."), + icon = "bucket_lava.png", +}) +awards.register_achievement("mcl:obsidian", { + title = S("Ice Bucket Challenge"), + description = S("Obtain an obsidian block."), + icon = "default_obsidian.png", +}) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 30e4075c86..0ba68b7231 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -207,6 +207,9 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { -- Fill bucket, but not in Creative Mode if not minetest.is_creative_enabled(user:get_player_name()) then new_bucket = ItemStack({name = liquiddef.itemname}) + if liquiddef.itemname == "mcl_buckets:bucket_lava" and awards and awards.unlock and user and user:is_player() then + awards.unlock(user:get_player_name(), "mcl:hotStuff") + end end minetest.add_node(pointed_thing.under, {name="air"}) diff --git a/mods/ITEMS/mcl_core/nodes_base.lua b/mods/ITEMS/mcl_core/nodes_base.lua index f4fe12155b..4477f0377b 100644 --- a/mods/ITEMS/mcl_core/nodes_base.lua +++ b/mods/ITEMS/mcl_core/nodes_base.lua @@ -33,6 +33,11 @@ minetest.register_node("mcl_core:stone", { _mcl_blast_resistance = 6, _mcl_hardness = 1.5, _mcl_silk_touch_drop = true, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + if awards and awards.unlock and digger and digger:is_player() then + awards.unlock(digger:get_player_name(), "mcl:stoneAge") + end + end, }) minetest.register_node("mcl_core:stone_with_coal", { @@ -814,6 +819,11 @@ minetest.register_node("mcl_core:obsidian", { groups = {pickaxey=5, building_block=1, material_stone=1}, _mcl_blast_resistance = 1200, _mcl_hardness = 50, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + if awards and awards.unlock and digger and digger:is_player() then + awards.unlock(digger:get_player_name(), "mcl:obsidian") + end + end, }) minetest.register_node("mcl_core:ice", { From 890a569b13cf0a9c9925dc545df740e201a6a2fb Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 07:40:36 +0200 Subject: [PATCH 050/234] add API documentation to mcl_worlds --- mods/CORE/mcl_worlds/API.md | 80 +++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 mods/CORE/mcl_worlds/API.md diff --git a/mods/CORE/mcl_worlds/API.md b/mods/CORE/mcl_worlds/API.md new file mode 100644 index 0000000000..a5509431c2 --- /dev/null +++ b/mods/CORE/mcl_worlds/API.md @@ -0,0 +1,80 @@ +# mcl_worlds +This mod provides utility functions about positions and dimensions. + +## mcl_worlds.is_in_void(pos) +This function returns: + +* true, true: if pos is in deep void (deadly) +* true, false: if the pos is in void (non deadly) +* false, false: owerwise + +Params: + +* pos: position + +## mcl_worlds.y_to_layer(y) +This function is used to calculate the minetest y layer and dimension of the given minecraft layer. +Mainly used for ore generation. +Takes an Y coordinate as input and returns: + +* The corresponding Minecraft layer (can be nil if void) +* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if is in the void +If the Y coordinate is not located in any dimension, it will return: nil, "void" + +Params: + +* y: int + +## mcl_worlds.pos_to_dimension(pos) +This function return the Minecraft dimension of ("overworld", "nether" or "end") or "void" if is in the void. + +* pos: position + +## mcl_worlds.layer_to_y(layer, mc_dimension) +Takes a Minecraft layer and a “dimension” name and returns the corresponding Y coordinate for MineClone 2. +mc_dimension can be "overworld", "nether", "end" (default: "overworld"). + +* layer: int +* mc_dimension: string + +## mcl_worlds.has_weather(pos) +Returns true if can have weather, false owerwise. +Weather can be only in the overworld. + +* pos: position + +## mcl_worlds.has_dust(pos) +Returns true if can have nether dust, false owerwise. +Nether dust can be only in the nether. + +* pos: position + +## mcl_worlds.compass_works(pos) +Returns true if compasses are working at , false owerwise. +In mc, you cant use compass in the nether and the end. + +* pos: position + +## mcl_worlds.compass_works(pos) +Returns true if clock are working at , false owerwise. +In mc, you cant use clock in the nether and the end. + +* pos: position + +## mcl_worlds.register_on_dimension_change(function(player, dimension)) +Register a callback function func(player, dimension). +It will be called whenever a player changes between dimensions. +The void counts as dimension. + +* player: player, the player who changed the dimension +* dimension: position, The new dimension of the player ("overworld", "nether", "end", "void"). + + +## mcl_worlds.registered_on_dimension_change +Table containing all function registered with mcl_worlds.register_on_dimension_change() + +## mcl_worlds.dimension_change(player, dimension) +Notify this mod of a dimmension change of to + +* player: player, player who changed the dimension +* dimension: string, new dimension ("overworld", "nether", "end", "void") \ No newline at end of file From c7389dc0a439364a214ff268005343428df4f533 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sun, 28 Mar 2021 08:13:24 +0200 Subject: [PATCH 051/234] add basic API to mcl_item_entity --- mods/ENTITIES/mcl_item_entity/init.lua | 39 ++++++++++++++++++++------ 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index d1d337a9cd..95b90e5467 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -1,3 +1,7 @@ +local has_awards = minetest.get_modpath("awards") + +mcl_item_entity = {} + --basic settings local item_drop_settings = {} --settings table item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting @@ -16,16 +20,33 @@ local get_gravity = function() return tonumber(minetest.settings:get("movement_gravity")) or 9.81 end +local registered_pickup_achievement = {} + +--TODO: remove limitation of 1 award per itemname +function mcl_item_entity.register_pickup_achievement(itemname, award) + if not has_awards then + minetest.log("warning", "[mcl_item_entity] Trying to register pickup achievement ["..award.."] for ["..itemname.."] while awards missing") + elseif registered_pickup_achievement[itemname] then + minetest.log("error", "[mcl_item_entity] Trying to register already existing pickup achievement ["..award.."] for ["..itemname.."]") + else + registered_pickup_achievement[itemname] = award + end +end + +mcl_item_entity.register_pickup_achievement("tree", "mcl:mineWood") +mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod") +mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow") +mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds") + local check_pickup_achievements = function(object, player) - local itemname = ItemStack(object:get_luaentity().itemstring):get_name() - if minetest.get_item_group(itemname, "tree") ~= 0 then - awards.unlock(player:get_player_name(), "mcl:mineWood") - elseif itemname == "mcl_mobitems:blaze_rod" then - awards.unlock(player:get_player_name(), "mcl:blazeRod") - elseif itemname == "mcl_mobitems:leather" then - awards.unlock(player:get_player_name(), "mcl:killCow") - elseif itemname == "mcl_core:diamond" then - awards.unlock(player:get_player_name(), "mcl:diamonds") + if has_awards then + local itemname = ItemStack(object:get_luaentity().itemstring):get_name() + local playername = player:get_player_name() + for name,award in pairs(registered_pickup_achievement) do + if itemname == name or minetest.get_item_group(itemname, name) ~= 0 then + awards.unlock(playername, award) + end + end end end From e76a0ba6e859a4aba665a849864f9799b87a8b87 Mon Sep 17 00:00:00 2001 From: iliekprogrammar Date: Sun, 28 Mar 2021 14:11:08 +0800 Subject: [PATCH 052/234] Added kelp API and additional refactorings. WIP: register nodetimers for kelp --- mods/ITEMS/mcl_ocean/kelp.lua | 499 ++++++++++++++++++++++------------ 1 file changed, 318 insertions(+), 181 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 73b2aaeb42..fe2266789c 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -1,94 +1,163 @@ -local S = minetest.get_translator("mcl_ocean") -local mod_doc = minetest.get_modpath("doc") ~= nil -- NOTE: whenever it becomes possible to fully implement kelp without the -- plantlike_rooted limitation, please adapt the code accordingly. -- TODO: In MC, you can't actually destroy kelp by bucket'ing water in the middle. -- However, because of the plantlike_rooted hack, we'll just allow it for now. --- List of supported surfaces for seagrass and kelp. -local surfaces = { - { "dirt", "mcl_core:dirt" }, - { "sand", "mcl_core:sand", 1 }, - { "redsand", "mcl_core:redsand", 1 }, - { "gravel", "mcl_core:gravel", 1 }, -} +local S = minetest.get_translator("mcl_ocean") +local mod_doc = minetest.get_modpath("doc") ~= nil + +-------------------------------------------------------------------------------- +-- local-ify runtime functions +-------------------------------------------------------------------------------- +-- objects +local registered_items = minetest.registered_items +local registered_nodes = minetest.registered_nodes + +-- functions +local mt_get_item_group = minetest.get_item_group +local mt_get_node = minetest.get_node +local mt_set_node = minetest.set_node +local mt_add_item = minetest.add_item +local mt_sound_play = minetest.sound_play +local mt_is_creative_enabled = minetest.is_creative_enabled +local mt_is_protected = minetest.is_protected +local mt_hash_node_position = minetest.hash_node_position +local mt_get_node_timer = minetest.get_node_timer + +-- DEBUG: functions +local chatlog = minetest.chat_send_all + +-------------------------------------------------------------------------------- +-- Kelp API +-------------------------------------------------------------------------------- + +kelp = {} -- Is this water? +-- Returns the liquidtype, if indeed water. local function is_submerged(node, nodedef) - if minetest.get_item_group(node.name, "water") ~= 0 then + if mt_get_item_group(node.name, "water") ~= 0 then return nodedef.liquidtype -- Expected only "source" and "flowing" from water liquids end return false end +kelp.is_submerged = is_submerged + -- Is the water downward flowing? -- (kelp can grow/be placed inside downward flowing water) local function is_downward_flowing(pos, node, nodedef, is_above) - - result = (math.floor(node.param2 / 8) % 2) == 1 + local result = (math.floor(node.param2 / 8) % 2) == 1 if not (result or is_above) then - -- If not, also check node above + -- If not, also check node above. -- (this is needed due a weird quirk in the definition of "downwards flowing" -- liquids in Minetest) - local node_above = minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}) - local nodedef_above = minetest.registered_nodes[node_above.name] + local node_above = mt_get_node({x=pos.x,y=pos.y+1,z=pos.z}) + local nodedef_above = registered_nodes[node_above.name] result = is_submerged(node_above, nodedef_above) or is_downward_flowing(pos, node_above, nodedef_above, true) end return result end +kelp.is_downward_flowing = is_downward_flowing + -- Converts param2 to kelp height. -local function get_kelp_height(param2) +local function get_height(param2) return math.floor(param2 / 16) end +kelp.get_height = get_height + -- Obtain pos and node of the top of kelp. -local function get_kelp_top(pos, node) +local function get_tip(pos, node) local size = math.ceil(node.param2 / 16) local pos_top = table.copy(pos) pos_top.y = pos_top.y + size - return pos_top, minetest.get_node(pos_top) + return pos_top, mt_get_node(pos_top) end +kelp.get_tip = get_tip + -- Obtain position of the first kelp unsubmerged. -local function get_kelp_unsubmerged(pos, node) +local function find_unsubmerged(pos, node) local x,y,z = pos.x, pos.y, pos.z - local height = get_kelp_height(node.param2) + local height = get_height(node.param2) for i=1,height do local walk_pos = {x=x, y=y + i, z=z} - if minetest.get_item_group(minetest.get_node(walk_pos).name, "water") == 0 then + if mt_get_item_group(mt_get_node(walk_pos).name, "water") == 0 then return walk_pos end end return nil end +kelp.find_unsubmerged = find_unsubmerged --- Obtain next param2 if grown -local function grow_param2_step(param2) - -- TODO: allow kelp to grow bypass this limit according to MC rules. - -- https://minecraft.gamepedia.com/Kelp +-- Obtain next param2. +local function next_param2(param2) local old_param2 = param2 param2 = param2+16 - param2 % 16 - if param2 > 240 then - param2 = 240 - end return param2, param2 ~= old_param2 end +kelp.next_param2 = next_param2 -local function kelp_place(pos, node, pos_top, def_top, is_downward_flowing) - -- Liquid source: Grow normally - minetest.set_node(pos, node) - -- Flowing liquid: Grow 1 step, but also turn the top node into a liquid source +-- Grow next kelp. +local function next_grow(pos, node, pos_top, def_top, is_downward_flowing) + -- Liquid source: Grow normally. + mt_set_node(pos, node) + + -- Flowing liquid: Grow 1 step, but also turn the top node into a liquid source. if is_downward_flowing then local alt_liq = def_top.liquid_alternative_source if alt_liq then - minetest.set_node(pos_top, {name=alt_liq}) + mt_set_node(pos_top, {name=alt_liq}) end end end +kelp.next_grow = next_grow + + +-- Drops the items for detached kelps. +local function detach_drop(pos, height) + local x,y,z = pos.x,pos.y,pos.z + for i=1,height do + mt_add_item({x=x, y=y+i, z=z}, "mcl_ocean:kelp") + end +end +kelp.detach_drop = detach_drop + + +-- Detach the kelp at dig_pos, and drop their items. +-- Synonyous to digging the kelp +local function detach_dig(dig_pos, pos, node, is_drop) + local param2 = node.param2 + -- pos.y points to the surface, offset needed to point to the first kelp. + local new_height = dig_pos.y - (pos.y+1) + + -- Digs the entire kelp: invoke after_dig_node to mt_set_node. + if new_height <= 0 then + if is_drop then + detach_drop(dig_pos, get_height(param2)) + end + mt_set_node(pos, { + name=registered_nodes[node.name].node_dig_prediction, + param=node.param, param2=0 }) + + -- Digs the kelp beginning at a height + else + if is_drop then + detach_drop(dig_pos, get_height(param2) - new_height) + end + mt_set_node(pos, {name=node.name, param=node.param, param2=16*new_height}) + end +end +kelp.detach_dig = detach_dig + +-------------------------------------------------------------------------------- +-- Kelp callback functions +-------------------------------------------------------------------------------- local function kelp_on_place(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" or not placer then @@ -98,17 +167,17 @@ local function kelp_on_place(itemstack, placer, pointed_thing) local player_name = placer:get_player_name() local pos_under = pointed_thing.under local pos_above = pointed_thing.above - local node_under = minetest.get_node(pos_under) + local node_under = mt_get_node(pos_under) local nu_name = node_under.name - local def_under = minetest.registered_nodes[nu_name] + local def_under = registered_nodes[nu_name] if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then return def_under.on_rightclick(pos_under, node_under, placer, itemstack, pointed_thing) or itemstack end - if minetest.is_protected(pos_under, player_name) or - minetest.is_protected(pos_above, player_name) then + if mt_is_protected(pos_under, player_name) or + mt_is_protected(pos_above, player_name) then minetest.log("action", player_name .. " tried to place " .. itemstack:get_name() .. " at protected position " @@ -122,23 +191,24 @@ local function kelp_on_place(itemstack, placer, pointed_thing) local pos_top, node_top, def_top -- When placed on kelp. - if minetest.get_item_group(nu_name, "kelp") == 1 then - node_under.param2, new_kelp = grow_param2_step(node_under.param2) + if mt_get_item_group(nu_name, "kelp") == 1 then + node_under.param2, new_kelp = next_param2(node_under.param2) -- Kelp must not reach the height limit. -- Kelp must also be placed on top of kelp to add kelp. if not new_kelp or pos_under.y >= pos_above.y then return itemstack end - pos_top, node_top = get_kelp_top(pos_under, node_under) - def_top = minetest.registered_nodes[node_top.name] + pos_top, node_top = get_tip(pos_under, node_under) + def_top = registered_nodes[node_top.name] -- When placed on surface. else + local surfaces = kelp.surfaces or surfaces for _,surface in pairs(surfaces) do -- Surface must support kelp - if nu_name == surface[2] then - node_under.name = "mcl_ocean:kelp_" ..surface[1] - node_under.param2 = minetest.registered_items[nu_name].place_param2 or 16 + if nu_name == surface.nodename then + node_under.name = "mcl_ocean:kelp_" ..surface.name + node_under.param2 = registered_items[nu_name].place_param2 or 16 new_kelp = true break end @@ -150,8 +220,8 @@ local function kelp_on_place(itemstack, placer, pointed_thing) end pos_top = pos_above - node_top = minetest.get_node(pos_above) - def_top = minetest.registered_nodes[node_top.name] + node_top = mt_get_node(pos_above) + def_top = registered_nodes[node_top.name] end -- New kelp must also be submerged in water. @@ -161,48 +231,193 @@ local function kelp_on_place(itemstack, placer, pointed_thing) end -- Play sound, place surface/kelp and take away an item - local def_node = minetest.registered_items[nu_name] + local def_node = registered_items[nu_name] if def_node.sounds then - minetest.sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) + mt_sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) end - kelp_place(pos_under, node_under, pos_top, def_top, downward_flowing) - if not minetest.is_creative_enabled(player_name) then + next_grow(pos_under, node_under, pos_top, def_top, downward_flowing) + if not mt_is_creative_enabled(player_name) then itemstack:take_item() end return itemstack end +kelp.kelp_on_place = kelp_on_place --- From kelp at pos, drop kelp until reaching its height. -local function kelp_drop(pos, height) - local x,y,z = pos.x,pos.y,pos.z - for i=1,height do - minetest.add_item({x=x, y=y+i, z=z}, "mcl_ocean:kelp") + +local function surface_on_dig(pos, node, digger) + -- TODO: poll on whether if players like dropping kelp in creative + -- detach_dig(pos, pos, node, + -- not (digger and mt_is_creative_enabled(digger:get_player_name()))) + detach_dig(pos, pos, node, true) +end +kelp.surface_on_dig = surface_on_dig + + +local function surface_after_dig_node(pos, node) + return mt_set_node(pos, {name=registred_nodes[node.name].node_dig_prediction}) +end +kelp.surface_after_dig_node = surface_after_dig_node + + +local function grow_kelp(pos, node) + local grow + -- Grow kelp by 1 node length if it would grow inside water + node.param2, grow = next_param2(node.param2) + local pos_top, node_top = get_tip(pos, node) + local def_top = registered_nodes[node_top.name] + if grow and is_submerged(node_top, def_top) then + next_grow(pos, node, pos_top, def_top, + is_downward_flowing(pos_top, node_top, def_top)) end end +kelp.grow_kelp = grow_kelp -local function kelp_dig(dig_pos, pos, node, is_drop) - local param2 = node.param2 - -- pos.y points to the surface, offset needed to point to the first kelp - local new_height = dig_pos.y - (pos.y+1) - -- Digs the entire kelp: invoke after_dig_node to set_node - if new_height <= 0 then - if is_drop then - kelp_drop(dig_pos, get_kelp_height(param2)) - end - minetest.set_node(pos, { - name=minetest.registered_nodes[node.name].node_dig_prediction, - param=node.param, param2=0 }) - - -- Digs the kelp beginning at a height - else - if is_drop then - kelp_drop(dig_pos, get_kelp_height(param2) - new_height) - end - minetest.set_node(pos, {name=node.name, param=node.param, param2=16*new_height}) +local kelp_timers_idx = {} +local kelp_timers = {} +local function surface_register_nodetimer(pos, node) + local pos_hash = mt_hash_node_position(pos) + if kelp_timers_idx[pos_hash] then + return end + local timer = mt_get_node_timer(pos) + table.insert(kelp_timers, timer) + kelp_timers_idx[pos_hash] = #kelp_timers + chatlog("added a timer. Currently " ..tostring(#kelp_timers) .." timers") end +kelp.surface_register_nodetiemr = surface_register_nodetimer + +-------------------------------------------------------------------------------- +-- Kelp registration API +-------------------------------------------------------------------------------- + +-- List of supported surfaces for seagrass and kelp. +local surfaces = { + { name="dirt", nodename="mcl_core:dirt", }, + { name="sand", nodename="mcl_core:sand", }, + { name="redsand", nodename="mcl_core:redsand", }, + { name="gravel", nodename="mcl_core:gravel", }, +} +kelp.surfaces = surfaces +local registered_surfaces = {} +kelp.registered_surfaces = registered_surfaces + +-- Commented keys are the ones obtained using register_kelp_surface. +-- If you define your own keys, that keys will be used instead. +local surface_deftemplate = { + drawtype = "plantlike_rooted", + paramtype = "light", + paramtype2 = "leveled", + place_param2 = 16, + --tiles = def.tiles, + special_tiles = { + { + image = "mcl_ocean_kelp_plant.png", + animation = {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}, + tileable_vertical = true, + } + }, + --inventory_image = "("..def.tiles[1]..")^mcl_ocean_kelp_item.png", + wield_image = "mcl_ocean_kelp_item.png", + selection_box = { + type = "fixed", + fixed = { + { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }, + { -0.5, 0.5, -0.5, 0.5, 1.5, 0.5 }, + }, + }, + -- groups.falling_node = is_falling, + groups = { dig_immediate = 3, deco_block = 1, plant = 1, kelp = 1, }, + --sounds = sounds, + --node_dig_prediction = nodename, + after_dig_node = surface_after_dig_node, + on_dig = surface_on_dig, + drop = "", -- drops are handled in on_dig + --_mcl_falling_node_alternative = is_falling and nodename or nil, + _mcl_hardness = 0, + _mcl_blast_resistance = 0, +} +kelp.surface_deftemplate = surface_deftemplate + +-- Commented keys are the ones obtained using register_kelp_surface. +local surface_docs = { + -- entry_id_orig = nodename, + _doc_items_entry_name = S("Kelp"), + _doc_items_longdesc = S("Kelp grows inside water on top of dirt, sand or gravel."), + --_doc_items_create_entry = doc_create, + _doc_items_image = "mcl_ocean_kelp_item.png", +} +kelp.surface_docs = surface_docs + +--[==[-- +register_kelp_surface(surface[, surface_deftemplate[, surface_docs]]) + +surface: table with the specifications below. See also kelp.surface. + { + name="dirt", + The name of the surface. This will appended to the surface's nodedef name + + nodename="mcl_core:dirt" + The nodename of the surface kelp can be planted on. + } + +surface_deftemplate: modifiable nodedef template. See also kelp.surface_deftempate. +DO NOT RE-USE THE SAME DEFTEMPLATE. create copies. + +surface_docs: table with keys related to docs. See also kelp.surface_docs. +--]==]-- +local leaf_sounds = mcl_sounds.node_sound_leaves_defaults() +local function register_kelp_surface(surface, surface_deftemplate, surface_docs) + local name = surface.name + local nodename = surface.nodename + local def = registered_nodes[nodename] + local def_tiles = def.tiles + + local surfacename = "mcl_ocean:kelp_"..name + local surface_deftemplate = surface_deftemplate or kelp.surface_deftemplate -- optional param + + local doc_create = surface.doc_create or false + local surface_docs = surface_docs or kelp.surface_docs + + if doc_create then + surface_deftemplate._doc_items_entry_name = surface_docs._doc_items_entry_name + surface_deftemplate._doc_items_longdesc = surface_docs._doc_items_longdesc + surface_deftemplate._doc_items_create_entry = true + surface_deftemplate._doc_items_image = surface_docs._doc_items_image + -- Takes the first surface with docs + if not surface_docs.entry_id_orig then + surface_docs.entry_id_orig = nodename + end + elseif mod_doc then + doc.add_entry_alias("nodes", surface_docs.entry_id_orig, "nodes", surfacename) + end + + local sounds = table.copy(def.sounds) + sounds.dig = leaf_sounds.dig + sounds.dug = leaf_sounds.dug + sounds.place = leaf_sounds.place + + surface_deftemplate.tiles = surface_deftemplate.tiles or def_tiles + surface_deftemplate.inventory_image = surface_deftemplate.inventory_image or "("..def_tiles[1]..")^mcl_ocean_kelp_item.png" + surface_deftemplate.sounds = surface_deftemplate.sound or sounds + local falling_node = mt_get_item_group(nodename, "falling_node") + surface_deftemplate.node_dig_prediction = surface_deftemplate.node_dig_prediction or nodename + surface_deftemplate.groups.faling_node = surface_deftemplate.groups.faling_node or falling_node + surface_deftemplate._mcl_falling_node_alternative = surface_deftemplate._mcl_falling_node_alternative or (falling_node and nodename or nil) + + minetest.register_node(surfacename, surface_deftemplate) +end + +-- Kelp surfaces nodes --------------------------------------------------------- + +-- Dirt must be registered first, for the docs +register_kelp_surface(surfaces[1], table.copy(surface_deftemplate), surface_docs) +for i=2, #surfaces do + register_kelp_surface(surfaces[i], table.copy(surface_deftemplate), surface_docs) +end + +-- Kelp item ------------------------------------------------------------------- minetest.register_craftitem("mcl_ocean:kelp", { description = S("Kelp"), @@ -214,86 +429,11 @@ minetest.register_craftitem("mcl_ocean:kelp", { groups = { deco_block = 1 }, }) --- Kelp nodes: kelp on a surface node - -for s=1, #surfaces do - local def = minetest.registered_nodes[surfaces[s][2]] - local alt - if surfaces[s][3] == 1 then - alt = surfaces[s][2] - end - local sounds = table.copy(def.sounds) - local leaf_sounds = mcl_sounds.node_sound_leaves_defaults() - sounds.dig = leaf_sounds.dig - sounds.dug = leaf_sounds.dug - sounds.place = leaf_sounds.place - local tt_help, doc_longdesc, doc_img, desc - if surfaces[s][1] == "dirt" then - doc_longdesc = S("Kelp grows inside water on top of dirt, sand or gravel.") - desc = S("Kelp") - doc_create = true - doc_img = "mcl_ocean_kelp_item.png" - else - doc_create = false - end - minetest.register_node("mcl_ocean:kelp_"..surfaces[s][1], { - _doc_items_entry_name = desc, - _doc_items_longdesc = doc_longdesc, - _doc_items_create_entry = doc_create, - _doc_items_image = doc_img, - drawtype = "plantlike_rooted", - paramtype = "light", - paramtype2 = "leveled", - place_param2 = 16, - tiles = def.tiles, - special_tiles = { - { - image = "mcl_ocean_kelp_plant.png", - animation = {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}, - tileable_vertical = true, - } - }, - inventory_image = "("..def.tiles[1]..")^mcl_ocean_kelp_item.png", - wield_image = "mcl_ocean_kelp_item.png", - selection_box = { - type = "fixed", - fixed = { - { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }, - { -0.5, 0.5, -0.5, 0.5, 1.5, 0.5 }, - }, - }, - groups = { dig_immediate = 3, deco_block = 1, plant = 1, kelp = 1, falling_node = surfaces[s][3] }, - sounds = sounds, - node_dig_prediction = surfaces[s][2], - after_dig_node = function(pos) - minetest.set_node(pos, {name=surface[s][2]}) - end, - -- TODO: add ability to detect whether the kelp or the surface is dug. - -- Currently, digging the surface gives sand, which isn't ideal. - on_dig = function(pos, node, digger) - minetest.chat_send_all("mo2") - local is_drop = true - if digger and minetest.is_creative_enabled(digger:get_player_name()) then - is_drop = false - end - kelp_dig(pos, pos, node, is_drop) - end, - drop = "", -- drops are handled in on_dig - _mcl_falling_node_alternative = alt, - _mcl_hardness = 0, - _mcl_blast_resistance = 0, - }) - - if mod_doc and surfaces[s][1] ~= "dirt" then - doc.add_entry_alias("nodes", "mcl_ocean:kelp_dirt", "nodes", "mcl_ocean:kelp_"..surfaces[s][1]) - end -end - if mod_doc then - doc.add_entry_alias("nodes", "mcl_ocean:kelp_dirt", "craftitems", "mcl_ocean:kelp") + doc.add_entry_alias("nodes", surface_docs.entry_id_orig, "craftitems", "mcl_ocean:kelp") end --- Dried kelp stuff +-- Dried kelp ------------------------------------------------------------------ -- TODO: This is supposed to be eaten very fast minetest.register_craftitem("mcl_ocean:dried_kelp", { @@ -308,13 +448,13 @@ minetest.register_craftitem("mcl_ocean:dried_kelp", { _mcl_saturation = 0.6, }) + local mod_screwdriver = minetest.get_modpath("screwdriver") ~= nil local on_rotate if mod_screwdriver then on_rotate = screwdriver.rotate_3way end - minetest.register_node("mcl_ocean:dried_kelp_block", { description = S("Dried Kelp Block"), _doc_items_longdesc = S("A decorative block that serves as a great furnace fuel."), @@ -354,39 +494,36 @@ minetest.register_craft({ burntime = 200, }) --- Grow kelp +-- ABMs ------------------------------------------------------------------------ minetest.register_abm({ - label = "Kelp growth", + label = "mcl_ocean:Kelp growth", nodenames = { "group:kelp" }, - -- interval = 45, - -- chance = 12, - interval = 1, - chance = 1, + interval = 45, + chance = 12, catch_up = false, - action = function(pos, node, active_object_count, active_object_count_wider) - local grow - -- Grow kelp by 1 node length if it would grow inside water - node.param2, grow = grow_param2_step(node.param2) - local pos_top, node_top = get_kelp_top(pos, node) - local def_top = minetest.registered_nodes[node_top.name] - if grow and is_submerged(node_top, def_top) then - kelp_place(pos, node, pos_top, def_top, - is_downward_flowing(pos_top, node_top, def_top)) - end - end, + action = grow_kelp, }) --- Break kelp not underwater. -minetest.register_abm({ - label = "Kelp drops", +minetest.register_lbm({ + label = "Kelp timer registration", + name = "mcl_ocean:kelp_timer_registration", nodenames = { "group:kelp" }, - interval = 0.25, - chance = 1, - catch_up = false, - action = function(pos, node) - local dig_pos = get_kelp_unsubmerged(pos, node) - if dig_pos then - kelp_dig(dig_pos, pos, node, true) - end - end + run_at_every_load = true, + action = surface_register_nodetimer, }) + +-- TODO: test if nodetimers are more efficient than ABM +-- -- Break kelp not underwater. +-- minetest.register_abm({ +-- label = "Kelp drops", +-- nodenames = { "group:kelp" }, +-- interval = 0.5, +-- chance = 1, +-- catch_up = false, +-- action = function(pos, node) +-- local dig_pos = find_unsubmerged(pos, node) +-- if dig_pos then +-- detach_dig(dig_pos, pos, node, true) +-- end +-- end +-- }) From 24da94ec3b413b1b41121e2003573cf45b810ed3 Mon Sep 17 00:00:00 2001 From: iliekprogrammar Date: Sun, 28 Mar 2021 20:29:29 +0800 Subject: [PATCH 053/234] Disable ABMs in favor of nodetimers to check if kelp is unsubmerged. --- mods/ITEMS/mcl_ocean/kelp.lua | 164 +++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 70 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index fe2266789c..a4de943b71 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -1,7 +1,11 @@ --- NOTE: whenever it becomes possible to fully implement kelp without the +-- TODO: whenever it becomes possible to fully implement kelp without the -- plantlike_rooted limitation, please adapt the code accordingly. +-- -- TODO: In MC, you can't actually destroy kelp by bucket'ing water in the middle. -- However, because of the plantlike_rooted hack, we'll just allow it for now. +-- +-- TODO: Currently, you lose kelp if the kelp is placed on a block and then falls. +-- This is most relevant for (red)sand and gravel. local S = minetest.get_translator("mcl_ocean") local mod_doc = minetest.get_modpath("doc") ~= nil @@ -25,6 +29,7 @@ local mt_hash_node_position = minetest.hash_node_position local mt_get_node_timer = minetest.get_node_timer -- DEBUG: functions +local log = minetest.log local chatlog = minetest.chat_send_all -------------------------------------------------------------------------------- @@ -130,7 +135,9 @@ kelp.detach_drop = detach_drop -- Detach the kelp at dig_pos, and drop their items. --- Synonyous to digging the kelp +-- Synonymous to digging the kelp. +-- NOTE: this is intended for whenever kelp truly becomes segmented plants +-- instead of rooted to the floor. Don't try to remove dig_pos. local function detach_dig(dig_pos, pos, node, is_drop) local param2 = node.param2 -- pos.y points to the surface, offset needed to point to the first kelp. @@ -159,6 +166,72 @@ kelp.detach_dig = detach_dig -- Kelp callback functions -------------------------------------------------------------------------------- +local function surface_on_dig(pos, node, digger) + -- NOTE: if instead, kelp shouldn't drop in creative: use this instead + -- detach_dig(pos, pos, node, + -- not (digger and mt_is_creative_enabled(digger:get_player_name()))) + detach_dig(pos, pos, node, true) +end +kelp.surface_on_dig = surface_on_dig + + +local function surface_after_dig_node(pos, node) + return mt_set_node(pos, {name=registred_nodes[node.name].node_dig_prediction}) +end +kelp.surface_after_dig_node = surface_after_dig_node + + +local kelp_timers = {} +local kelp_timers_counter = 0 +local function surface_on_timer(pos, elapsed) + local node = mt_get_node(pos) + local dig_pos = find_unsubmerged(pos, node) + if dig_pos then + detach_dig(dig_pos, pos, node, true) + end + return true +end + + +-- NOTE: Uncomment this to use ABMs +-- local function surface_unsubmerged_abm(pos, node) +-- local dig_pos = find_unsubmerged(pos, node) +-- if dig_pos then +-- detach_dig(dig_pos, pos, node, true) +-- end +-- return true +-- end + + +-- NOTE: Uncomment this to use nodetimers +local function surface_register_nodetimer(pos, node) + local pos_hash = mt_hash_node_position(pos) + if kelp_timers[pos_hash] then + return + end + local timer = mt_get_node_timer(pos) + kelp_timers[pos_hash] = timer + timer:start(0.5) + kelp_timers_counter = kelp_timers_counter + 1 + chatlog("added a timer. Currently " ..tostring(kelp_timers_counter) .." timers") +end +kelp.surface_register_nodetiemr = surface_register_nodetimer + + +local function grow_kelp(pos, node) + local grow + -- Grow kelp by 1 node length if it would grow inside water + node.param2, grow = next_param2(node.param2) + local pos_top, node_top = get_tip(pos, node) + local def_top = registered_nodes[node_top.name] + if grow and is_submerged(node_top, def_top) then + next_grow(pos, node, pos_top, def_top, + is_downward_flowing(pos_top, node_top, def_top)) + end +end +kelp.grow_kelp = grow_kelp + + local function kelp_on_place(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" or not placer then return itemstack @@ -171,6 +244,7 @@ local function kelp_on_place(itemstack, placer, pointed_thing) local nu_name = node_under.name local def_under = registered_nodes[nu_name] + -- Allow rightclick override. if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then return def_under.on_rightclick(pos_under, node_under, placer, itemstack, pointed_thing) or itemstack @@ -222,6 +296,10 @@ local function kelp_on_place(itemstack, placer, pointed_thing) pos_top = pos_above node_top = mt_get_node(pos_above) def_top = registered_nodes[node_top.name] + + -- NOTE: Uncomment this to use nodetimers + -- Register nodetimer + surface_register_nodetimer(pos_under, node_under) end -- New kelp must also be submerged in water. @@ -244,50 +322,6 @@ local function kelp_on_place(itemstack, placer, pointed_thing) end kelp.kelp_on_place = kelp_on_place - -local function surface_on_dig(pos, node, digger) - -- TODO: poll on whether if players like dropping kelp in creative - -- detach_dig(pos, pos, node, - -- not (digger and mt_is_creative_enabled(digger:get_player_name()))) - detach_dig(pos, pos, node, true) -end -kelp.surface_on_dig = surface_on_dig - - -local function surface_after_dig_node(pos, node) - return mt_set_node(pos, {name=registred_nodes[node.name].node_dig_prediction}) -end -kelp.surface_after_dig_node = surface_after_dig_node - - -local function grow_kelp(pos, node) - local grow - -- Grow kelp by 1 node length if it would grow inside water - node.param2, grow = next_param2(node.param2) - local pos_top, node_top = get_tip(pos, node) - local def_top = registered_nodes[node_top.name] - if grow and is_submerged(node_top, def_top) then - next_grow(pos, node, pos_top, def_top, - is_downward_flowing(pos_top, node_top, def_top)) - end -end -kelp.grow_kelp = grow_kelp - - -local kelp_timers_idx = {} -local kelp_timers = {} -local function surface_register_nodetimer(pos, node) - local pos_hash = mt_hash_node_position(pos) - if kelp_timers_idx[pos_hash] then - return - end - local timer = mt_get_node_timer(pos) - table.insert(kelp_timers, timer) - kelp_timers_idx[pos_hash] = #kelp_timers - chatlog("added a timer. Currently " ..tostring(#kelp_timers) .." timers") -end -kelp.surface_register_nodetiemr = surface_register_nodetimer - -------------------------------------------------------------------------------- -- Kelp registration API -------------------------------------------------------------------------------- @@ -303,8 +337,8 @@ kelp.surfaces = surfaces local registered_surfaces = {} kelp.registered_surfaces = registered_surfaces --- Commented keys are the ones obtained using register_kelp_surface. --- If you define your own keys, that keys will be used instead. +-- Commented properties are the ones obtained using register_kelp_surface. +-- If you define your own properties, it overrides the default ones. local surface_deftemplate = { drawtype = "plantlike_rooted", paramtype = "light", @@ -333,6 +367,7 @@ local surface_deftemplate = { --node_dig_prediction = nodename, after_dig_node = surface_after_dig_node, on_dig = surface_on_dig, + on_timer = surface_on_timer, drop = "", -- drops are handled in on_dig --_mcl_falling_node_alternative = is_falling and nodename or nil, _mcl_hardness = 0, @@ -340,7 +375,7 @@ local surface_deftemplate = { } kelp.surface_deftemplate = surface_deftemplate --- Commented keys are the ones obtained using register_kelp_surface. +-- Commented properties are the ones obtained using register_kelp_surface. local surface_docs = { -- entry_id_orig = nodename, _doc_items_entry_name = S("Kelp"), @@ -353,19 +388,12 @@ kelp.surface_docs = surface_docs --[==[-- register_kelp_surface(surface[, surface_deftemplate[, surface_docs]]) -surface: table with the specifications below. See also kelp.surface. - { - name="dirt", - The name of the surface. This will appended to the surface's nodedef name - - nodename="mcl_core:dirt" - The nodename of the surface kelp can be planted on. - } +surface: table with its specific properties. See also kelp.surface. surface_deftemplate: modifiable nodedef template. See also kelp.surface_deftempate. DO NOT RE-USE THE SAME DEFTEMPLATE. create copies. -surface_docs: table with keys related to docs. See also kelp.surface_docs. +surface_docs: table with properties related to docs. See also kelp.surface_docs. --]==]-- local leaf_sounds = mcl_sounds.node_sound_leaves_defaults() local function register_kelp_surface(surface, surface_deftemplate, surface_docs) @@ -403,7 +431,7 @@ local function register_kelp_surface(surface, surface_deftemplate, surface_docs) surface_deftemplate.sounds = surface_deftemplate.sound or sounds local falling_node = mt_get_item_group(nodename, "falling_node") surface_deftemplate.node_dig_prediction = surface_deftemplate.node_dig_prediction or nodename - surface_deftemplate.groups.faling_node = surface_deftemplate.groups.faling_node or falling_node + surface_deftemplate.groups.falling_node = surface_deftemplate.groups.falling_node or falling_node surface_deftemplate._mcl_falling_node_alternative = surface_deftemplate._mcl_falling_node_alternative or (falling_node and nodename or nil) minetest.register_node(surfacename, surface_deftemplate) @@ -496,7 +524,7 @@ minetest.register_craft({ -- ABMs ------------------------------------------------------------------------ minetest.register_abm({ - label = "mcl_ocean:Kelp growth", + label = "Kelp growth", nodenames = { "group:kelp" }, interval = 45, chance = 12, @@ -504,26 +532,22 @@ minetest.register_abm({ action = grow_kelp, }) +-- NOTE: Uncomment this to use nodetimers minetest.register_lbm({ label = "Kelp timer registration", name = "mcl_ocean:kelp_timer_registration", nodenames = { "group:kelp" }, - run_at_every_load = true, + run_at_every_load = false, action = surface_register_nodetimer, }) --- TODO: test if nodetimers are more efficient than ABM --- -- Break kelp not underwater. +-- NOTE: Uncomment this to use ABMs +-- Break kelp not underwater. -- minetest.register_abm({ -- label = "Kelp drops", -- nodenames = { "group:kelp" }, --- interval = 0.5, +-- interval = 1.0, -- chance = 1, -- catch_up = false, --- action = function(pos, node) --- local dig_pos = find_unsubmerged(pos, node) --- if dig_pos then --- detach_dig(dig_pos, pos, node, true) --- end --- end +-- action = surface_unsubmerged_abm, -- }) From 628ca226a611b470bb0fb4f684d48f469968c9f4 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 28 Mar 2021 20:36:35 +0400 Subject: [PATCH 054/234] [mcl_portals] Additionally index source Nether portals from 0.71 and earlier before teleporting, to make possible returning through them --- mods/ITEMS/mcl_portals/portal_nether.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 29368af307..1fe9e26b78 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -381,6 +381,12 @@ local function finalize_teleport(obj, exit) objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)} if mcl_portals.get_node(objpos).name ~= PORTAL then return end + -- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- 1 of 2 -- TODO: Remove -- + -- Old worlds have no exits indexed - adding the exit to return here: + add_exit(objpos) + -- TEMPORATY CODE SECTION ENDS HERE -- + + -- Enable teleportation cooloff for some seconds, to prevent back-and-forth teleportation teleport_cooloff(obj) @@ -436,7 +442,8 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param) local pos0, distance local lava = get_lava_level(pos, pos1, pos2) - -- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- + -- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- 2 of 2 -- TODO: Remove -- + -- Find portals for old worlds (new worlds keep them all in the table): local portals = find_nodes_in_area(pos1, pos2, {PORTAL}) if portals and #portals>0 then for _, p in pairs(portals) do From cb2aae5a55549e6644b3ad76f467917c600d33cf Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 28 Mar 2021 22:56:51 +0400 Subject: [PATCH 055/234] [mcl_mapgen_core] Redesign, mostly to remove water from End and restore static lvm_buffer to speed it up --- mods/CORE/mcl_init/init.lua | 83 ++++++++++++++++ mods/ITEMS/mcl_portals/portal_nether.lua | 17 +--- mods/MAPGEN/mcl_dungeons/init.lua | 26 ++--- mods/MAPGEN/mcl_mapgen_core/init.lua | 118 ++++------------------- mods/MAPGEN/mcl_structures/init.lua | 2 +- mods/MAPGEN/mcl_villages/buildings.lua | 2 +- mods/MAPGEN/mcl_villages/foundation.lua | 2 +- mods/MAPGEN/mcl_villages/utils.lua | 35 ++----- 8 files changed, 127 insertions(+), 158 deletions(-) diff --git a/mods/CORE/mcl_init/init.lua b/mods/CORE/mcl_init/init.lua index ca510b74f9..014a30d1e3 100644 --- a/mods/CORE/mcl_init/init.lua +++ b/mods/CORE/mcl_init/init.lua @@ -175,3 +175,86 @@ minetest.craftitemdef_default.stack_max = 64 -- Set random seed for all other mods (Remember to make sure no other mod calls this function) math.randomseed(os.time()) +local chunks = {} -- intervals of chunks generated +function mcl_vars.add_chunk(pos) + local n = mcl_vars.get_chunk_number(pos) -- unsigned int + local prev + for i, d in pairs(chunks) do + if n <= d[2] then -- we've found it + if (n == d[2]) or (n >= d[1]) then return end -- already here + if n == d[1]-1 then -- right before: + if prev and (prev[2] == n-1) then + prev[2] = d[2] + table.remove(chunks, i) + return + end + d[1] = n + return + end + if prev and (prev[2] == n-1) then --join to previous + prev[2] = n + return + end + table.insert(chunks, i, {n, n}) -- insert new interval before i + return + end + prev = d + end + chunks[#chunks+1] = {n, n} +end +function mcl_vars.is_generated(pos) + local n = mcl_vars.get_chunk_number(pos) -- unsigned int + for i, d in pairs(chunks) do + if n <= d[2] then + return (n >= d[1]) + end + end + return false +end + +-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does. +-- p: Position, if it's wrong, {name="error"} node will return. +-- force: optional (default: false) - Do the maximum to still read the node within us_timeout. +-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job. +-- +-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}. +function mcl_vars.get_node(p, force, us_timeout) + -- check initial circumstances + if not p or not p.x or not p.y or not p.z then return {name="error"} end + + -- try common way + local node = minetest.get_node(p) + if node.name ~= "ignore" then + return node + end + + -- copy table to get sure it won't changed by other threads + local pos = {x=p.x,y=p.y,z=p.z} + + -- try LVM + minetest.get_voxel_manip():read_from_map(pos, pos) + node = minetest.get_node(pos) + if node.name ~= "ignore" or not force then + return node + end + + -- all ways failed - need to emerge (or forceload if generated) + local us_timeout = us_timeout or 244 + if mcl_vars.is_generated(pos) then + minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!") + minetest.forceload_block(pos) + else + minetest.emerge_area(pos, pos) + end + + local t = minetest.get_us_time() + + node = minetest.get_node(pos) + + while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do + node = minetest.get_node(pos) + end + + return node + -- it still can return "ignore", LOL, even if force = true, but only after time out +end diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 1fe9e26b78..7d28c921a2 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -66,12 +66,7 @@ minetest.register_on_shutdown(function() storage:set_string("nether_exits_keys", minetest.serialize(keys)) end) -mcl_portals.get_node = function(pos) - if mcl_mapgen_core and mcl_mapgen_core.get_node then - mcl_portals.get_node = mcl_mapgen_core.get_node - end - return minetest.get_node(pos) -end +local get_node = mcl_vars.get_node local set_node = minetest.set_node local registered_nodes = minetest.registered_nodes local is_protected = minetest.is_protected @@ -97,7 +92,6 @@ local limits = { -- Incoming verification performed: two nodes must be portal nodes, and an obsidian below them. -- If the verification passes - position adds to the table and saves to mod storage on exit. local function add_exit(p) - local get_node = mcl_portals.get_node if not p or not p.y or not p.z or not p.x then return end local x, y, z = floor(p.x), floor(p.y), floor(p.z) local p = {x = x, y = y, z = z} @@ -202,7 +196,6 @@ local function destroy_nether_portal(pos, node) local nn, orientation = node.name, node.param2 local obsidian = nn == OBSIDIAN - local get_node = mcl_portals.get_node local check_remove = function(pos, orientation) local node = get_node(pos) if node and (node.name == PORTAL and (orientation == nil or (node.param2 == orientation))) then @@ -315,8 +308,6 @@ function build_nether_portal(pos, width, height, orientation, name) light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1)) - local get_node = mcl_portals.get_node - -- Build obsidian platform: for x = pos.x - orientation, pos.x + orientation + (width - 1) * (1 - orientation), 1 + orientation do for z = pos.z - 1 + orientation, pos.z + 1 - orientation + (width - 1) * orientation, 2 - orientation do @@ -379,7 +370,7 @@ local function finalize_teleport(obj, exit) -- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)} - if mcl_portals.get_node(objpos).name ~= PORTAL then return end + if get_node(objpos).name ~= PORTAL then return end -- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- 1 of 2 -- TODO: Remove -- -- Old worlds have no exits indexed - adding the exit to return here: @@ -529,7 +520,7 @@ local function create_portal(pos, limit1, limit2, name, obj) end local function available_for_nether_portal(p) - local nn = mcl_portals.get_node(p).name + local nn = get_node(p).name local obsidian = nn == OBSIDIAN if nn ~= "air" and minetest.get_item_group(nn, "fire") ~= 1 then return false, obsidian @@ -636,7 +627,7 @@ local function teleport_no_delay(obj, pos) -- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)} - if mcl_portals.get_node(objpos).name ~= PORTAL then return end + if get_node(objpos).name ~= PORTAL then return end local target, dim = get_target(objpos) if not target then return end diff --git a/mods/MAPGEN/mcl_dungeons/init.lua b/mods/MAPGEN/mcl_dungeons/init.lua index 05d82c3e9c..5c15d6309d 100644 --- a/mods/MAPGEN/mcl_dungeons/init.lua +++ b/mods/MAPGEN/mcl_dungeons/init.lua @@ -12,6 +12,8 @@ end local min_y = math.max(mcl_vars.mg_overworld_min, mcl_vars.mg_bedrock_overworld_max) + 1 local max_y = mcl_vars.mg_overworld_max - 1 +local get_node = mcl_vars.get_node + -- Calculate the number of dungeon spawn attempts -- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks). -- Minetest chunks don't have this size, so scale the number accordingly. @@ -49,8 +51,8 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) local y_floor = y local y_ceiling = y + dim.y + 1 if check then for tx = x+1, x+dim.x do for tz = z+1, z+dim.z do - if not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_floor , z = tz}).name].walkable - or not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end + if not minetest.registered_nodes[get_node({x = tx, y = y_floor , z = tz}).name].walkable + or not minetest.registered_nodes[get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end end end end -- Check for air openings (2 stacked air at ground level) in wall positions @@ -63,25 +65,25 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) local x2,z2 = x+dim.x+1, z+dim.z+1 - if mcl_mapgen_core.get_node({x=x, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z}).name == "air" then + if get_node({x=x, y=y+1, z=z}).name == "air" and get_node({x=x, y=y+2, z=z}).name == "air" then openings_counter = openings_counter + 1 if not openings[x] then openings[x]={} end openings[x][z] = true table.insert(corners, {x=x, z=z}) end - if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z}).name == "air" then + if get_node({x=x2, y=y+1, z=z}).name == "air" and get_node({x=x2, y=y+2, z=z}).name == "air" then openings_counter = openings_counter + 1 if not openings[x2] then openings[x2]={} end openings[x2][z] = true table.insert(corners, {x=x2, z=z}) end - if mcl_mapgen_core.get_node({x=x, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z2}).name == "air" then + if get_node({x=x, y=y+1, z=z2}).name == "air" and get_node({x=x, y=y+2, z=z2}).name == "air" then openings_counter = openings_counter + 1 if not openings[x] then openings[x]={} end openings[x][z2] = true table.insert(corners, {x=x, z=z2}) end - if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z2}).name == "air" then + if get_node({x=x2, y=y+1, z=z2}).name == "air" and get_node({x=x2, y=y+2, z=z2}).name == "air" then openings_counter = openings_counter + 1 if not openings[x2] then openings[x2]={} end openings[x2][z2] = true @@ -89,13 +91,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) end for wx = x+1, x+dim.x do - if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z}).name == "air" then + if get_node({x=wx, y=y+1, z=z}).name == "air" and get_node({x=wx, y=y+2, z=z}).name == "air" then openings_counter = openings_counter + 1 if check and openings_counter > 5 then return end if not openings[wx] then openings[wx]={} end openings[wx][z] = true end - if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z2}).name == "air" then + if get_node({x=wx, y=y+1, z=z2}).name == "air" and get_node({x=wx, y=y+2, z=z2}).name == "air" then openings_counter = openings_counter + 1 if check and openings_counter > 5 then return end if not openings[wx] then openings[wx]={} end @@ -103,13 +105,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) end end for wz = z+1, z+dim.z do - if mcl_mapgen_core.get_node({x=x, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=wz}).name == "air" then + if get_node({x=x, y=y+1, z=wz}).name == "air" and get_node({x=x, y=y+2, z=wz}).name == "air" then openings_counter = openings_counter + 1 if check and openings_counter > 5 then return end if not openings[x] then openings[x]={} end openings[x][wz] = true end - if mcl_mapgen_core.get_node({x=x2, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=wz}).name == "air" then + if get_node({x=x2, y=y+1, z=wz}).name == "air" and get_node({x=x2, y=y+2, z=wz}).name == "air" then openings_counter = openings_counter + 1 if check and openings_counter > 5 then return end if not openings[x2] then openings[x2]={} end @@ -185,7 +187,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) -- Calculate the mob spawner position, to be re-used for later local sp = {x = x + math.ceil(dim.x/2), y = y+1, z = z + math.ceil(dim.z/2)} - local rn = minetest.registered_nodes[mcl_mapgen_core.get_node(sp).name] + local rn = minetest.registered_nodes[get_node(sp).name] if rn and rn.is_ground_content then table.insert(spawner_posses, sp) end @@ -200,7 +202,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) -- Do not overwrite nodes with is_ground_content == false (e.g. bedrock) -- Exceptions: cobblestone and mossy cobblestone so neighborings dungeons nicely connect to each other - local name = mcl_mapgen_core.get_node(p).name + local name = get_node(p).name if minetest.registered_nodes[name].is_ground_content or name == "mcl_core:cobble" or name == "mcl_core:mossycobble" then -- Floor if ty == y then diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 496b2e222d..63256ec7ab 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -1,45 +1,8 @@ mcl_mapgen_core = {} -mcl_mapgen_core.registered_generators = {} +local registered_generators = {} local lvm, nodes, param2 = 0, 0, 0 - -local generating = {} -- generating chunks -local chunks = {} -- intervals of chunks generated -local function add_chunk(pos) - local n = mcl_vars.get_chunk_number(pos) -- unsigned int - local prev - for i, d in pairs(chunks) do - if n <= d[2] then -- we've found it - if (n == d[2]) or (n >= d[1]) then return end -- already here - if n == d[1]-1 then -- right before: - if prev and (prev[2] == n-1) then - prev[2] = d[2] - table.remove(chunks, i) - return - end - d[1] = n - return - end - if prev and (prev[2] == n-1) then --join to previous - prev[2] = n - return - end - table.insert(chunks, i, {n, n}) -- insert new interval before i - return - end - prev = d - end - chunks[#chunks+1] = {n, n} -end -function mcl_mapgen_core.is_generated(pos) - local n = mcl_vars.get_chunk_number(pos) -- unsigned int - for i, d in pairs(chunks) do - if n <= d[2] then - return (n >= d[1]) - end - end - return false -end +local lvm_buffer = {} -- -- Aliases for map generator outputs @@ -1850,24 +1813,22 @@ end minetest.register_on_generated(function(minp, maxp, blockseed) minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp)) - add_chunk(minp) local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z} if lvm > 0 then local lvm_used, shadow = false, false - local lb = {} -- buffer local lb2 = {} -- param2 local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z} local data2 - local data = vm:get_data(lb) + local data = vm:get_data(lvm_buffer) if param2 > 0 then data2 = vm:get_param2_data(lb2) end local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2}) - for _, rec in pairs(mcl_mapgen_core.registered_generators) do + for _, rec in pairs(registered_generators) do if rec.vf then - local lvm_used0, shadow0 = rec.vf(vm, data, data2, p1, p2, area, p1, p2, blockseed) + local lvm_used0, shadow0 = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed) if lvm_used0 then lvm_used = true end @@ -1890,18 +1851,18 @@ minetest.register_on_generated(function(minp, maxp, blockseed) end if nodes > 0 then - for _, rec in pairs(mcl_mapgen_core.registered_generators) do + for _, rec in pairs(registered_generators) do if rec.nf then rec.nf(p1, p2, blockseed) end end end --- add_chunk(minp) + mcl_vars.add_chunk(minp) end) minetest.register_on_generated=function(node_function) - mcl_mapgen_core.register_generator("mod_"..tostring(#mcl_mapgen_core.registered_generators+1), nil, node_function) + mcl_mapgen_core.register_generator("mod_"..tostring(#registered_generators+1), nil, node_function) end function mcl_mapgen_core.register_generator(id, lvm_function, node_function, priority, needs_param2) @@ -1920,18 +1881,18 @@ function mcl_mapgen_core.register_generator(id, lvm_function, node_function, pri needs_param2 = needs_param2, } - mcl_mapgen_core.registered_generators[id] = new_record + registered_generators[id] = new_record table.sort( - mcl_mapgen_core.registered_generators, + registered_generators, function(a, b) return (a.i < b.i) or ((a.i == b.i) and (a.vf ~= nil) and (b.vf == nil)) end) end function mcl_mapgen_core.unregister_generator(id) - if not mcl_mapgen_core.registered_generators[id] then return end - local rec = mcl_mapgen_core.registered_generators[id] - mcl_mapgen_core.registered_generators[id] = nil + if not registered_generators[id] then return end + local rec = registered_generators[id] + registered_generators[id] = nil if rec.vf then lvm = lvm - 1 end if rev.nf then nodes = nodes - 1 end if rec.needs_param2 then param2 = param2 - 1 end @@ -2134,9 +2095,9 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) -- Nether block fixes: -- * Replace water with Nether lava. -- * Replace stone, sand dirt in v6 so the Nether works in v6. - elseif minp.y <= mcl_vars.mg_nether_max and maxp.y >= mcl_vars.mg_nether_min then + elseif emin.y <= mcl_vars.mg_nether_max and emax.y >= mcl_vars.mg_nether_min then if mg_name == "v6" then - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) for n=1, #nodes do local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) if data[p_pos] == c_water then @@ -2151,7 +2112,7 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) end end else - minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining, param) + minetest.emerge_area(emin, emax, function(blockpos, action, calls_remaining, param) if calls_remaining > 0 then return end -- local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"mcl_core:water_source"}) local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"group:water"}) @@ -2160,7 +2121,7 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) for _, n in pairs(nodes) do sn(n, l) end - end, {minp=vector.new(minp), maxp=vector.new(maxp)}) + end, {minp=vector.new(emin), maxp=vector.new(emax)}) end -- End block fixes: @@ -2231,48 +2192,3 @@ end mcl_mapgen_core.register_generator("main", basic, nil, 1, true) --- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like 5.3.0 does. --- p: Position, if it's wrong, {name="error"} node will return. --- force: optional (default: false) - Do the maximum to still read the node within us_timeout. --- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job. --- --- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}. -function mcl_mapgen_core.get_node(p, force, us_timeout) - -- check initial circumstances - if not p or not p.x or not p.y or not p.z then return {name="error"} end - - -- try common way - local node = minetest.get_node(p) - if node.name ~= "ignore" then - return node - end - - -- copy table to get sure it won't changed by other threads - local pos = {x=p.x,y=p.y,z=p.z} - - -- try LVM - minetest.get_voxel_manip():read_from_map(pos, pos) - node = minetest.get_node(pos) - if node.name ~= "ignore" or not force then - return node - end - - -- all ways failed - need to emerge (or forceload if generated) - local us_timeout = us_timeout or 244 - if mcl_mapgen_core.is_generated(pos) then - minetest.forceload_block(pos) - else - minetest.emerge_area(pos, pos) - end - - local t = minetest.get_us_time() - - node = minetest.get_node(pos) - - while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do - node = minetest.get_node(pos) - end - - return node - -- it still can return "ignore", LOL, even if force = true, but only after time out -end diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 0d6bc62ab8..f6317bdeb3 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -272,7 +272,7 @@ local function hut_placement_callback(p1, p2, size, orientation, pr) if not p1 or not p2 then return end local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree") for i = 1, #legs do - while minetest.get_item_group(mcl_mapgen_core.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do + while minetest.get_item_group(mcl_vars.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do legs[i].y = legs[i].y - 1 minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2}) end diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua index 18d6c1e0bb..e43db6d987 100644 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ b/mods/MAPGEN/mcl_villages/buildings.lua @@ -4,7 +4,7 @@ ------------------------------------------------------------------------------- function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name) -- get building node material for better integration to surrounding - local platform_material = mcl_mapgen_core.get_node(pos) + local platform_material = mcl_vars.get_node(pos) if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then return end diff --git a/mods/MAPGEN/mcl_villages/foundation.lua b/mods/MAPGEN/mcl_villages/foundation.lua index 67a2385f7b..038a2f2020 100644 --- a/mods/MAPGEN/mcl_villages/foundation.lua +++ b/mods/MAPGEN/mcl_villages/foundation.lua @@ -52,7 +52,7 @@ function settlements.terraform(settlement_info, pr) else -- write ground -- local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi} --- local node = mcl_mapgen_core.get_node(p) +-- local node = mcl_vars.get_node(p) -- if node and node.name ~= "air" then -- minetest.swap_node(p,{name="air"}) -- end diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua index 2d96ba26fc..d7617541dc 100644 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ b/mods/MAPGEN/mcl_villages/utils.lua @@ -1,28 +1,5 @@ -local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") -local c_dirt_with_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow") ---local c_dirt_with_dry_grass = minetest.get_content_id("mcl_core:dirt_with_dry_grass") -local c_podzol = minetest.get_content_id("mcl_core:podzol") -local c_sand = minetest.get_content_id("mcl_core:sand") -local c_desert_sand = minetest.get_content_id("mcl_core:redsand") ---local c_silver_sand = minetest.get_content_id("mcl_core:silver_sand") --- -local c_air = minetest.get_content_id("air") -local c_snow = minetest.get_content_id("mcl_core:snow") -local c_fern_1 = minetest.get_content_id("mcl_flowers:fern") -local c_fern_2 = minetest.get_content_id("mcl_flowers:fern") -local c_fern_3 = minetest.get_content_id("mcl_flowers:fern") -local c_rose = minetest.get_content_id("mcl_flowers:poppy") -local c_viola = minetest.get_content_id("mcl_flowers:blue_orchid") -local c_geranium = minetest.get_content_id("mcl_flowers:allium") -local c_tulip = minetest.get_content_id("mcl_flowers:tulip_orange") -local c_dandelion_y = minetest.get_content_id("mcl_flowers:dandelion") -local c_dandelion_w = minetest.get_content_id("mcl_flowers:oxeye_daisy") -local c_bush_leaves = minetest.get_content_id("mcl_core:leaves") -local c_bush_stem = minetest.get_content_id("mcl_core:tree") -local c_a_bush_leaves = minetest.get_content_id("mcl_core:acacialeaves") -local c_a_bush_stem = minetest.get_content_id("mcl_core:acaciatree") -local c_water_source = minetest.get_content_id("mcl_core:water_source") -local c_water_flowing = minetest.get_content_id("mcl_core:water_flowing") +local get_node = mcl_vars.get_node + ------------------------------------------------------------------------------- -- function to copy tables ------------------------------------------------------------------------------- @@ -53,9 +30,9 @@ function settlements.find_surface(pos, wait) -- check, in which direction to look for surface local surface_node if wait then - surface_node = mcl_mapgen_core.get_node(p6, true, 10000000) + surface_node = get_node(p6, true, 10000000) else - surface_node = mcl_mapgen_core.get_node(p6) + surface_node = get_node(p6) end if surface_node.name=="air" or surface_node.name=="ignore" then itter = -1 @@ -65,7 +42,7 @@ function settlements.find_surface(pos, wait) -- Check Surface_node and Node above -- if settlements.surface_mat[surface_node.name] then - local surface_node_plus_1 = mcl_mapgen_core.get_node({ x=p6.x, y=p6.y+1, z=p6.z}) + local surface_node_plus_1 = get_node({ x=p6.x, y=p6.y+1, z=p6.z}) if surface_node_plus_1 and surface_node and (string.find(surface_node_plus_1.name,"air") or string.find(surface_node_plus_1.name,"snow") or @@ -90,7 +67,7 @@ function settlements.find_surface(pos, wait) return nil end cnt = cnt+1 - surface_node = mcl_mapgen_core.get_node(p6) + surface_node = get_node(p6) end settlements.debug("find_surface5: cnt_max overflow") return nil From 05260d03d595d31e0061854987ea1bc95a63821e Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 29 Mar 2021 01:33:01 +0400 Subject: [PATCH 056/234] [mcl_portals] Fix crash on access empty index trying to find portal after its destruction --- mods/ITEMS/mcl_portals/portal_nether.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 7d28c921a2..5bb2264081 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -103,7 +103,7 @@ local function add_exit(p) local e = exits[k] for i = 1, #e do local t = e[i] - if t.x == p.x and t.y == p.y and t.z == p.z then + if t and t.x == p.x and t.y == p.y and t.z == p.z then return end end From bbd52043f11656c91dee07063bae1f56703c6dd9 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 29 Mar 2021 02:17:32 +0400 Subject: [PATCH 057/234] [mcl_portals] Make '/spawnstruct nether_portal' chat command work in obsidian nodes (immediate destruction triggered) --- mods/ITEMS/mcl_portals/portal_nether.lua | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 5bb2264081..6e2d1e7b6f 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -278,12 +278,14 @@ minetest.register_node(PORTAL, { _mcl_blast_resistance = 0, }) -local function light_frame(x1, y1, z1, x2, y2, z2, name) +local function light_frame(x1, y1, z1, x2, y2, z2, name, node, node_frame) local orientation = 0 if x1 == x2 then orientation = 1 end local pos = {} + local node = node or {name = PORTAL, param2 = orientation} + local node_frame = node_frame or {name = OBSIDIAN} for x = x1 - 1 + orientation, x2 + 1 - orientation do pos.x = x for z = z1 - orientation, z2 + orientation do @@ -292,9 +294,9 @@ local function light_frame(x1, y1, z1, x2, y2, z2, name) pos.y = y local frame = (x < x1) or (x > x2) or (y < y1) or (y > y2) or (z < z1) or (z > z2) if frame then - set_node(pos, {name = OBSIDIAN}) + set_node(pos, node_frame) else - set_node(pos, {name = PORTAL, param2 = orientation}) + set_node(pos, node) add_exit({x=pos.x, y=pos.y-1, z=pos.z}) end end @@ -303,10 +305,13 @@ local function light_frame(x1, y1, z1, x2, y2, z2, name) end --Build arrival portal -function build_nether_portal(pos, width, height, orientation, name) +function build_nether_portal(pos, width, height, orientation, name, clear_before_build) local width, height, orientation = width or W_MIN - 2, height or H_MIN - 2, orientation or random(0, 1) - light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1)) + if clear_before_build then + light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1), name, {name="air"}, {name="air"}) + end + light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1), name) -- Build obsidian platform: for x = pos.x - orientation, pos.x + orientation + (width - 1) * (1 - orientation), 1 + orientation do @@ -336,7 +341,7 @@ function mcl_portals.spawn_nether_portal(pos, rot, pr, name) o = random(0,1) end end - build_nether_portal(pos, nil, nil, o, name) + build_nether_portal(pos, nil, nil, o, name, true) end -- Teleportation cooloff for some seconds, to prevent back-and-forth teleportation From 1818fcf5929f51b1d57a57b9880e2a01f1fda390 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 29 Mar 2021 02:43:08 +0400 Subject: [PATCH 058/234] [mcl_mapgen_core] Remove water from End, fix https://git.minetest.land/MineClone2/MineClone2/issues/1394 --- mods/MAPGEN/mcl_mapgen_core/init.lua | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 63256ec7ab..1a2abf3f93 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -2129,17 +2129,16 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. -- * Generate spawn platform (End portal destination) elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then - local nodes, node + local nodes, n if mg_name == "v6" then - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) else - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) + nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"}) end if #nodes > 0 then lvm_used = true - for n=1, #nodes do - node = nodes[n] - data[area:index(node.x, node.y, node.z)] = c_air + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_air end end From b587b1f2a5ace2acb8d7912ac2bbd1a619cc60dd Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 29 Mar 2021 02:48:45 +0400 Subject: [PATCH 059/234] [mcl_spawn] Cleanup --- mods/PLAYER/mcl_spawn/init.lua | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/mods/PLAYER/mcl_spawn/init.lua b/mods/PLAYER/mcl_spawn/init.lua index 6a3d543d3c..55329c104d 100644 --- a/mods/PLAYER/mcl_spawn/init.lua +++ b/mods/PLAYER/mcl_spawn/init.lua @@ -81,13 +81,7 @@ local dir_step = storage:get_int("mcl_spawn_dir_step") or 0 local dir_ind = storage:get_int("mcl_spawn_dir_ind") or 1 local emerge_pos1, emerge_pos2 --- Get world 'mapgen_limit' and 'chunksize' to calculate 'spawn_limit'. --- This accounts for how mapchunks are not generated if they or their shell exceed --- 'mapgen_limit'. - -local mapgen_limit = tonumber(minetest.get_mapgen_setting("mapgen_limit")) -local chunksize = tonumber(minetest.get_mapgen_setting("chunksize")) -local spawn_limit = math.max(mapgen_limit - (chunksize + 1) * 16, 0) +local spawn_limit = mcl_vars.mapgen_edge_max --Functions From 2e3a5efaf90d9812b98726d46630433c29144dba Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 29 Mar 2021 03:08:21 +0400 Subject: [PATCH 060/234] [mcl_spawn] Ignore 'ignore' nodes when checking the point, fix https://git.minetest.land/MineClone2/MineClone2/issues/1230 --- mods/PLAYER/mcl_spawn/init.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mods/PLAYER/mcl_spawn/init.lua b/mods/PLAYER/mcl_spawn/init.lua index 55329c104d..fe88cf3de6 100644 --- a/mods/PLAYER/mcl_spawn/init.lua +++ b/mods/PLAYER/mcl_spawn/init.lua @@ -497,10 +497,17 @@ function mcl_spawn.shadow_worker() mcl_spawn.search() minetest.log("action", "[mcl_spawn] Started world spawn point search") end - if success and ((not good_for_respawn(wsp)) or (not can_find_tree(wsp))) then - success = false - minetest.log("action", "[mcl_spawn] World spawn position isn't safe anymore: "..minetest.pos_to_string(wsp)) - mcl_spawn.search() + + if success then + local wsp_node = minetest.get_node(wsp) + if wsp_node and wsp_node.name == "ignore" then + -- special case - respawn area unloaded from memory - it's okay, skip for now + + elseif ((not good_for_respawn(wsp)) or ((no_trees_area_counter >= 0) and not can_find_tree(wsp))) then + success = false + minetest.log("action", "[mcl_spawn] World spawn position isn't safe anymore: "..minetest.pos_to_string(wsp)) + mcl_spawn.search() + end end minetest.after(respawn_search_interval, mcl_spawn.shadow_worker) From 80d845adb678e568ed67d081771b04cc0dd85ef5 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 29 Mar 2021 03:18:17 +0400 Subject: [PATCH 061/234] [mcl_mapgen_core] Fix Nether generation chain reaction --- mods/ITEMS/mcl_portals/portal_nether.lua | 1 - mods/MAPGEN/mcl_mapgen_core/init.lua | 14 ++++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 6e2d1e7b6f..e842edf812 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -466,7 +466,6 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param) local nodes2 = find_nodes_in_area(node1, node2, {"air"}) if nodes2 then local nc2 = #nodes2 - log("action", "[mcl_portals] nc2=" .. tostring(nc2)) if nc2 == 27 and not is_area_protected(node, node2, name) then local distance0 = dist(pos, node) if distance0 < 2 then diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 1a2abf3f93..e08b55ba30 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -2112,16 +2112,10 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) end end else - minetest.emerge_area(emin, emax, function(blockpos, action, calls_remaining, param) - if calls_remaining > 0 then return end - -- local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"mcl_core:water_source"}) - local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"group:water"}) - local sn=(mcl_observers and mcl_observers.swap_node) or minetest.swap_node - local l = {name="mcl_nether:nether_lava_source"} - for _, n in pairs(nodes) do - sn(n, l) - end - end, {minp=vector.new(emin), maxp=vector.new(emax)}) + local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"}) + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_nether_lava + end end -- End block fixes: From d1a0299b9202d501c21851c9beb9c82b63a15cbe Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 29 Mar 2021 03:34:41 +0400 Subject: [PATCH 062/234] [mcl_dungeons] Remove empty code section, add debug info --- mods/MAPGEN/mcl_dungeons/init.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mods/MAPGEN/mcl_dungeons/init.lua b/mods/MAPGEN/mcl_dungeons/init.lua index 5c15d6309d..dc9c6d6198 100644 --- a/mods/MAPGEN/mcl_dungeons/init.lua +++ b/mods/MAPGEN/mcl_dungeons/init.lua @@ -247,7 +247,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) if forChest and (currentChest < totalChests + 1) and (chestSlots[currentChest] == chestSlotCounter) then currentChest = currentChest + 1 table.insert(chests, {x=tx, y=ty, z=tz}) - else + -- else --minetest.swap_node(p, {name = "air"}) end if forChest then @@ -265,8 +265,8 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) -- Detect the 4 horizontal neighbors local spos = vector.add(pos, surround_vectors[s]) local wpos = vector.subtract(pos, surround_vectors[s]) - local nodename = minetest.get_node(spos).name - local nodename2 = minetest.get_node(wpos).name + local nodename = get_node(spos).name + local nodename2 = get_node(wpos).name local nodedef = minetest.registered_nodes[nodename] local nodedef2 = minetest.registered_nodes[nodename2] -- The chest needs an open space in front of it and a walkable node (except chest) behind it @@ -347,6 +347,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) }) end + minetest.log("action", "[mcl_dungeons] Filling chest " .. tostring(c) .. " at " .. minetest.pos_to_string(pos)) mcl_loot.fill_inventory(meta:get_inventory(), "main", mcl_loot.get_multi_loot(loottable, pr), pr) end From ecdbc30b63998e4fdcb3004ca892707b54bd7d2f Mon Sep 17 00:00:00 2001 From: iliekprogrammar Date: Mon, 29 Mar 2021 14:09:09 +0800 Subject: [PATCH 063/234] Overhaul kelp interactions. Highlights: - Added locking system to drops. Will be removed after testing. - Expose more variables and functions. Will be finalized soon. - Implement MC-like age and natural growth mechanics. - Implement correct piston interactions with kelp and its surface. - Implement correct falling node interactions for its surface. - ABMs are now nonfunction. Will be fixed. - Various optimizations and fixes. --- mods/ITEMS/mcl_ocean/init.lua | 2 + mods/ITEMS/mcl_ocean/kelp.lua | 484 ++++++++++++++++++++++------------ 2 files changed, 320 insertions(+), 166 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/init.lua b/mods/ITEMS/mcl_ocean/init.lua index 2a103b8d05..f723a1f3ff 100644 --- a/mods/ITEMS/mcl_ocean/init.lua +++ b/mods/ITEMS/mcl_ocean/init.lua @@ -1,3 +1,5 @@ +mcl_ocean = {} + -- Prismarine (includes sea lantern) dofile(minetest.get_modpath(minetest.get_current_modname()).."/prismarine.lua") diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index a4de943b71..741d9e59aa 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -3,9 +3,6 @@ -- -- TODO: In MC, you can't actually destroy kelp by bucket'ing water in the middle. -- However, because of the plantlike_rooted hack, we'll just allow it for now. --- --- TODO: Currently, you lose kelp if the kelp is placed on a block and then falls. --- This is most relevant for (red)sand and gravel. local S = minetest.get_translator("mcl_ocean") local mod_doc = minetest.get_modpath("doc") ~= nil @@ -14,19 +11,28 @@ local mod_doc = minetest.get_modpath("doc") ~= nil -- local-ify runtime functions -------------------------------------------------------------------------------- -- objects -local registered_items = minetest.registered_items -local registered_nodes = minetest.registered_nodes +local mt_registered_items = minetest.registered_items +local mt_registered_nodes = minetest.registered_nodes -- functions +local mt_add_item = minetest.add_item local mt_get_item_group = minetest.get_item_group local mt_get_node = minetest.get_node -local mt_set_node = minetest.set_node -local mt_add_item = minetest.add_item -local mt_sound_play = minetest.sound_play -local mt_is_creative_enabled = minetest.is_creative_enabled -local mt_is_protected = minetest.is_protected -local mt_hash_node_position = minetest.hash_node_position +local mt_get_node_level = minetest.get_node_level +local mt_get_node_max_level = minetest.get_node_max_level +local mt_get_node_or_nil = minetest.get_node_or_nil local mt_get_node_timer = minetest.get_node_timer +local mt_hash_node_position = minetest.hash_node_position +local mt_is_protected = minetest.is_protected +local mt_set_node = minetest.set_node +local mt_get_meta = minetest.get_meta + +local mt_is_creative_enabled = minetest.is_creative_enabled +local mt_sound_play = minetest.sound_play + +local math_floor = math.floor +local math_random = math.random +local string_format = string.format -- DEBUG: functions local log = minetest.log @@ -36,109 +42,218 @@ local chatlog = minetest.chat_send_all -- Kelp API -------------------------------------------------------------------------------- -kelp = {} +local kelp = {} +mcl_ocean.kelp = kelp + +kelp.MAX_AGE = 25 +kelp.TIMER_INTERVAL = 0.2 + +-- The average amount of growth for kelp in a day is 2.16 (https://youtu.be/5Bp4lAjAk3I) +-- Normally, a day lasts 20 minutes, meaning this nodetimer is executed 24000 times. +-- Calculate probability via 2.16/24000 and we get the probability 9/100'000 or 9.0e-5 +-- NOTE: currently, we can't exactly use the same type of randomness MC does, +-- because it has multiple complicated sets of PRNGs. +-- kelp.RANDOM_NUMERATOR = 9 +kelp.RANDOM_NUMERATOR = 100 +kelp.RANDOM_DENOMINATOR = 100000 + +kelp.leaf_sounds = mcl_sounds.node_sound_leaves_defaults() + +-- TODO: is this really necessary +-- Lock drops to avoid duplicate drops, set after dropping detached kelp. +kelp.lock_drop = 0 + +-- Registrar of nodetimers, indexed by pos_hash. +kelp.registered_nodetimers = {} + +-- Pool storing age, indexed by pos_hash. +kelp.age_pool = {} + + +-- is age in the growable range? +function kelp.is_age_growable(age) + return age >= 0 and age < kelp.MAX_AGE +end + -- Is this water? -- Returns the liquidtype, if indeed water. -local function is_submerged(node, nodedef) +function kelp.is_submerged(node, def) if mt_get_item_group(node.name, "water") ~= 0 then - return nodedef.liquidtype -- Expected only "source" and "flowing" from water liquids + return def.liquidtype -- Expected only "source" and "flowing" from water liquids end return false end -kelp.is_submerged = is_submerged -- Is the water downward flowing? -- (kelp can grow/be placed inside downward flowing water) -local function is_downward_flowing(pos, node, nodedef, is_above) - local result = (math.floor(node.param2 / 8) % 2) == 1 +function kelp.is_downward_flowing(pos, node, def, is_above) + local result = (math_floor(node.param2 / 8) % 2) == 1 if not (result or is_above) then -- If not, also check node above. -- (this is needed due a weird quirk in the definition of "downwards flowing" -- liquids in Minetest) local node_above = mt_get_node({x=pos.x,y=pos.y+1,z=pos.z}) - local nodedef_above = registered_nodes[node_above.name] - result = is_submerged(node_above, nodedef_above) - or is_downward_flowing(pos, node_above, nodedef_above, true) + local def_above = mt_registered_nodes[node_above.name] + result = kelp.is_submerged(node_above, def_above) + or kelp.is_downward_flowing(pos, node_above, def_above, true) end return result end -kelp.is_downward_flowing = is_downward_flowing + + +-- Will node fall at that position? +-- This only checks if a node would fall, meaning that node need not be at pos. +function kelp.is_falling(pos, node) + -- NOTE: Modified from check_single_for_falling in builtin. + -- Please update as necessary. + local nodename = node.name + + if mt_get_item_group(nodename, "falling_node") == 0 then + return false + end + + local pos_bottom = {x = pos.x, y = pos.y - 1, z = pos.z} + -- get_node_or_nil: Only fall if node below is loaded + local node_bottom = mt_get_node_or_nil(pos_bottom) + local nodename_bottom = node_bottom.name + local def_bottom = node_bottom and mt_registered_nodes[nodename_bottom] + if not def_bottom then + return false + end + + local same = nodename == nodename_bottom + -- Let leveled nodes fall if it can merge with the bottom node + if same and def_bottom.paramtype2 == "leveled" and + mt_get_node_level(pos_bottom) < + mt_get_node_max_level(pos_bottom) then + return true + end + + -- Otherwise only if the bottom node is considered "fall through" + if not same and + (not def_bottom.walkable or def_bottom.buildable_to) and + (mt_get_item_group(nodename, "float") == 0 or + def_bottom.liquidtype == "none") then + return true + end + + return false +end -- Converts param2 to kelp height. -local function get_height(param2) - return math.floor(param2 / 16) +function kelp.get_height(param2) + return math_floor(param2 / 16) end -kelp.get_height = get_height --- Obtain pos and node of the top of kelp. -local function get_tip(pos, node) +-- Obtain pos and node of the tip of kelp. +function kelp.get_tip(pos, node) local size = math.ceil(node.param2 / 16) - local pos_top = table.copy(pos) - pos_top.y = pos_top.y + size - return pos_top, mt_get_node(pos_top) + local pos_tip = table.copy(pos) + pos_tip.y = pos_tip.y + size + return pos_tip, mt_get_node(pos_tip) end -kelp.get_tip = get_tip -- Obtain position of the first kelp unsubmerged. -local function find_unsubmerged(pos, node) +function kelp.find_unsubmerged(pos, node) + local x,y,z = pos.x, pos.y, pos.z - local height = get_height(node.param2) + local height = kelp.get_height(node.param2) + local walk_pos = {x=x, z=z} for i=1,height do - local walk_pos = {x=x, y=y + i, z=z} - if mt_get_item_group(mt_get_node(walk_pos).name, "water") == 0 then - return walk_pos + walk_pos.y = y + i + local walk_node = mt_get_node(walk_pos) + if mt_get_item_group(walk_node.name, "water") == 0 then + return walk_pos, walk_node end end return nil end -kelp.find_unsubmerged = find_unsubmerged -- Obtain next param2. -local function next_param2(param2) - local old_param2 = param2 - param2 = param2+16 - param2 % 16 - return param2, param2 ~= old_param2 +function kelp.next_param2(param2) + return param2+16 - param2 % 16 end -kelp.next_param2 = next_param2 -- Grow next kelp. -local function next_grow(pos, node, pos_top, def_top, is_downward_flowing) +function kelp.next_grow(pos, node, pos_tip, def_tip, downward_flowing) + -- Optional parameters + local pos_tip, def_tip = pos_tip, def_tip + local downward_flowing = downward_flowing + if pos_tip == nil and def_tip == nil then + local node_tip + pos_tip, node_tip = kelp.get_tip(pos, node) + def_tip = mt_registered_nodes[node_tip.name] + downward_flowing = kelp.is_submerged(pos_tip, node_tip) + and kelp.is_downward_flowing(pos_tip, node_tip, def_tip) + end + -- Liquid source: Grow normally. + local node = table.copy(node) + node.param2 = kelp.next_param2(node.param2) mt_set_node(pos, node) - -- Flowing liquid: Grow 1 step, but also turn the top node into a liquid source. - if is_downward_flowing then - local alt_liq = def_top.liquid_alternative_source + -- Flowing liquid: Grow 1 step, but also turn the tip node into a liquid source. + if downward_flowing then + local alt_liq = def_tip.liquid_alternative_source if alt_liq then - mt_set_node(pos_top, {name=alt_liq}) + mt_set_node(pos_tip, {name=alt_liq}) end end end -kelp.next_grow = next_grow + + +-- Naturally grow next kelp. +function kelp.natural_grow(pos, node, age, pos_hash, meta) + -- Must grow first, then get the new meta + kelp.next_grow(pos, node) + + -- Optional params + local meta = meta or mt_get_meta(pos) + local pos_hash = pos_hash or mt_hash_node_position(pos) + + local age = age + 1 + kelp.age_pool[pos_hash] = age + meta:set_int("mcl_ocean:kelp_age", age) + +end -- Drops the items for detached kelps. -local function detach_drop(pos, height) +function kelp.detach_drop(pos, height, pos_hash) + local pos_hash = pos_hash or mt_hash_node_position(pos) -- Optional params + + if kelp.lock_drop > 0 then + minetest.log("error", + string_format("Duplicate drop prevented at (%d, %d, %d) with lock level %d! Please report this.", + pos.x, pos.y, pos.z, kelp.lock_drop)) + return + end + local x,y,z = pos.x,pos.y,pos.z for i=1,height do mt_add_item({x=x, y=y+i, z=z}, "mcl_ocean:kelp") end + + -- Locks drop. + kelp.lock_drop = kelp.lock_drop + 1 + return true end -kelp.detach_drop = detach_drop -- Detach the kelp at dig_pos, and drop their items. -- Synonymous to digging the kelp. -- NOTE: this is intended for whenever kelp truly becomes segmented plants -- instead of rooted to the floor. Don't try to remove dig_pos. -local function detach_dig(dig_pos, pos, node, is_drop) +function kelp.detach_dig(dig_pos, pos, node, is_drop, pos_hash) + local pos_hash = pos_hash or mt_hash_node_position(pos) + local param2 = node.param2 -- pos.y points to the surface, offset needed to point to the first kelp. local new_height = dig_pos.y - (pos.y+1) @@ -146,52 +261,77 @@ local function detach_dig(dig_pos, pos, node, is_drop) -- Digs the entire kelp: invoke after_dig_node to mt_set_node. if new_height <= 0 then if is_drop then - detach_drop(dig_pos, get_height(param2)) + kelp.detach_drop(dig_pos, kelp.get_height(param2), pos_hash) end mt_set_node(pos, { - name=registered_nodes[node.name].node_dig_prediction, + name=mt_registered_nodes[node.name].node_dig_prediction, param=node.param, param2=0 }) -- Digs the kelp beginning at a height else if is_drop then - detach_drop(dig_pos, get_height(param2) - new_height) + kelp.detach_drop(dig_pos, kelp.get_height(param2) - new_height, pos_hash) end mt_set_node(pos, {name=node.name, param=node.param, param2=16*new_height}) end end -kelp.detach_dig = detach_dig + -------------------------------------------------------------------------------- -- Kelp callback functions -------------------------------------------------------------------------------- -local function surface_on_dig(pos, node, digger) - -- NOTE: if instead, kelp shouldn't drop in creative: use this instead - -- detach_dig(pos, pos, node, - -- not (digger and mt_is_creative_enabled(digger:get_player_name()))) - detach_dig(pos, pos, node, true) +-- Set this to drop kelps when +function kelp.surface_on_dig(pos, node, digger) + kelp.detach_dig(pos, pos, node, true) end -kelp.surface_on_dig = surface_on_dig -local function surface_after_dig_node(pos, node) +function kelp.surface_after_dig_node(pos, node) return mt_set_node(pos, {name=registred_nodes[node.name].node_dig_prediction}) end -kelp.surface_after_dig_node = surface_after_dig_node -local kelp_timers = {} -local kelp_timers_counter = 0 -local function surface_on_timer(pos, elapsed) +function kelp.surface_on_timer(pos, elapsed) local node = mt_get_node(pos) - local dig_pos = find_unsubmerged(pos, node) + local dig_pos = kelp.find_unsubmerged(pos, node) + local pos_hash = mt_hash_node_position(pos) if dig_pos then - detach_dig(dig_pos, pos, node, true) + kelp.detach_dig(dig_pos, pos, node, true, pos_hash) end + + -- Grow kelp on chance + if math_random(kelp.RANDOM_DENOMINATOR) - kelp.RANDOM_NUMERATOR < 0 then + local age = kelp.age_pool[pos_hash] + if kelp.is_age_growable(age) then + kelp.natural_grow(pos, node, age, pos_hash) + end + end + return true end +function kelp.surface_on_destruct(pos) + local node = mt_get_node(pos) + local pos_hash = mt_hash_node_position(pos) + + -- on_falling callback. Activated by pistons for falling nodes too. + if kelp.is_falling(pos, node) then + kelp.detach_drop(pos, kelp.get_height(node.param2), pos_hash) + end + + -- Unlocks drops. + if kelp.lock_drop > 0 then + kelp.lock_drop = kelp.lock_drop - 1 + end +end + + +function kelp.surface_on_mvps_move(pos, node, oldpos, nodemeta) + -- Pistons moving falling nodes will have already activated on_falling callback. + kelp.detach_dig(pos, pos, node, mt_get_item_group(node.name, "falling_node") ~= 1) +end + -- NOTE: Uncomment this to use ABMs -- local function surface_unsubmerged_abm(pos, node) @@ -204,35 +344,52 @@ end -- NOTE: Uncomment this to use nodetimers -local function surface_register_nodetimer(pos, node) - local pos_hash = mt_hash_node_position(pos) - if kelp_timers[pos_hash] then - return +function kelp.surface_register_nodetimer(pos, node, pos_hash, meta, age) + -- Optional params + local pos_hash,meta,age = pos_hash,meta,age + local timer = kelp.registered_nodetimers[pos_hash] + + if not timer then + pos_hash = pos_hash or mt_hash_node_position(pos) + + timer = mt_get_node_timer(pos) + kelp.registered_nodetimers[pos_hash] = timer + + -- Pool age to avoid meta:get* operations + meta = meta or mt_get_meta(pos) + if not age then + if not meta:contains("mcl_ocean:kelp_age") then + age = math_random(0, kelp.MAX_AGE-1) + else + age = meta:get_int("mcl_ocean:kelp_age") + end + end + kelp.age_pool[pos_hash] = age + meta:set_int("mcl_ocean:kelp_age", age) end - local timer = mt_get_node_timer(pos) - kelp_timers[pos_hash] = timer - timer:start(0.5) - kelp_timers_counter = kelp_timers_counter + 1 - chatlog("added a timer. Currently " ..tostring(kelp_timers_counter) .." timers") -end -kelp.surface_register_nodetiemr = surface_register_nodetimer - -local function grow_kelp(pos, node) - local grow - -- Grow kelp by 1 node length if it would grow inside water - node.param2, grow = next_param2(node.param2) - local pos_top, node_top = get_tip(pos, node) - local def_top = registered_nodes[node_top.name] - if grow and is_submerged(node_top, def_top) then - next_grow(pos, node, pos_top, def_top, - is_downward_flowing(pos_top, node_top, def_top)) + if not timer:is_started() then + timer:start(kelp.TIMER_INTERVAL) end + + return pos_hash, meta, age end -kelp.grow_kelp = grow_kelp -local function kelp_on_place(itemstack, placer, pointed_thing) +-- NOTE: Uncomment this to use ABMs +-- function kelp.grow_abm(pos, node) +-- -- Grow kelp by 1 node length if it would grow inside water +-- node.param2 = next_param2(node.param2) +-- local pos_tip, node_tip = get_tip(pos, node) +-- local def_tip = mt_registered_nodes[node_tip.name] +-- if is_submerged(node_tip, def_tip) then +-- kelp.next_grow(pos, node, pos_tip, def_tip, +-- is_downward_flowing(pos_tip, node_tip, def_tip)) +-- end +-- end + + +function kelp.kelp_on_place(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" or not placer then return itemstack end @@ -242,14 +399,15 @@ local function kelp_on_place(itemstack, placer, pointed_thing) local pos_above = pointed_thing.above local node_under = mt_get_node(pos_under) local nu_name = node_under.name - local def_under = registered_nodes[nu_name] + local def_under = mt_registered_nodes[nu_name] - -- Allow rightclick override. + -- Allow rightclick to override place. if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then return def_under.on_rightclick(pos_under, node_under, placer, itemstack, pointed_thing) or itemstack end + -- Protection if mt_is_protected(pos_under, player_name) or mt_is_protected(pos_above, player_name) then minetest.log("action", player_name @@ -260,86 +418,89 @@ local function kelp_on_place(itemstack, placer, pointed_thing) return itemstack end - local new_kelp = false - local downward_flowing = false - local pos_top, node_top, def_top + + local pos_tip, node_tip, def_tip + local pos_hash, meta + + + -- Kelp must also be placed on the top/tip side of the surface/kelp + if pos_under.y >= pos_above.y then + return itemstack + end -- When placed on kelp. if mt_get_item_group(nu_name, "kelp") == 1 then - node_under.param2, new_kelp = next_param2(node_under.param2) - -- Kelp must not reach the height limit. - -- Kelp must also be placed on top of kelp to add kelp. - if not new_kelp or pos_under.y >= pos_above.y then - return itemstack - end - pos_top, node_top = get_tip(pos_under, node_under) - def_top = registered_nodes[node_top.name] + pos_tip, node_tip = kelp.get_tip(pos_under, node_under) + def_tip = mt_registered_nodes[node_tip.name] + + pos_hash = mt_hash_node_position(pos_under) + meta = mt_get_meta(pos_under) -- When placed on surface. else - local surfaces = kelp.surfaces or surfaces - for _,surface in pairs(surfaces) do - -- Surface must support kelp + local new_kelp = false + for _,surface in pairs(kelp.surfaces) do if nu_name == surface.nodename then node_under.name = "mcl_ocean:kelp_" ..surface.name - node_under.param2 = registered_items[nu_name].place_param2 or 16 + node_under.param2 = 0 new_kelp = true break end end - - -- Kelp must also be placed on top of surface to add new kelp. - if not new_kelp or pos_under.y >= pos_above.y then + -- Surface must support kelp + if not new_kelp then return itemstack end - pos_top = pos_above - node_top = mt_get_node(pos_above) - def_top = registered_nodes[node_top.name] - -- NOTE: Uncomment this to use nodetimers -- Register nodetimer - surface_register_nodetimer(pos_under, node_under) + pos_hash, meta = kelp.surface_register_nodetimer(pos_under) + + pos_tip = pos_above + node_tip = mt_get_node(pos_above) + def_tip = mt_registered_nodes[node_tip.name] end -- New kelp must also be submerged in water. - downward_flowing = is_downward_flowing(pos_top, node_top, def_top) - if not (is_submerged(node_top, def_top) or downward_flowing) then + local downward_flowing = kelp.is_downward_flowing(pos_tip, node_tip, def_tip) + if not (kelp.is_submerged(node_tip, def_tip) or downward_flowing) then return itemstack end -- Play sound, place surface/kelp and take away an item - local def_node = registered_items[nu_name] + local def_node = mt_registered_items[nu_name] if def_node.sounds then mt_sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) end - next_grow(pos_under, node_under, pos_top, def_top, downward_flowing) + kelp.next_grow(pos_under, node_under, pos_tip, def_tip, downward_flowing) if not mt_is_creative_enabled(player_name) then itemstack:take_item() end + -- Reroll age + local age = math_random(0, kelp.MAX_AGE-1) + meta:set_int("mcl_ocean:kelp_age", age) + kelp.age_pool[pos_hash] = age + return itemstack end -kelp.kelp_on_place = kelp_on_place -------------------------------------------------------------------------------- -- Kelp registration API -------------------------------------------------------------------------------- -- List of supported surfaces for seagrass and kelp. -local surfaces = { +kelp.surfaces = { { name="dirt", nodename="mcl_core:dirt", }, { name="sand", nodename="mcl_core:sand", }, { name="redsand", nodename="mcl_core:redsand", }, { name="gravel", nodename="mcl_core:gravel", }, } -kelp.surfaces = surfaces -local registered_surfaces = {} -kelp.registered_surfaces = registered_surfaces +kelp.registered_surfaces = {} -- Commented properties are the ones obtained using register_kelp_surface. -- If you define your own properties, it overrides the default ones. -local surface_deftemplate = { +kelp.surface_deftemplate = { drawtype = "plantlike_rooted", paramtype = "light", paramtype2 = "leveled", @@ -365,55 +526,46 @@ local surface_deftemplate = { groups = { dig_immediate = 3, deco_block = 1, plant = 1, kelp = 1, }, --sounds = sounds, --node_dig_prediction = nodename, - after_dig_node = surface_after_dig_node, - on_dig = surface_on_dig, - on_timer = surface_on_timer, + after_dig_node = kelp.surface_after_dig_node, + on_destruct = kelp.surface_on_destruct, + on_dig = kelp.surface_on_dig, + on_timer = kelp.surface_on_timer, + mesecon = { on_mvps_move = kelp.surface_on_mvps_move, }, drop = "", -- drops are handled in on_dig --_mcl_falling_node_alternative = is_falling and nodename or nil, _mcl_hardness = 0, _mcl_blast_resistance = 0, } -kelp.surface_deftemplate = surface_deftemplate -- Commented properties are the ones obtained using register_kelp_surface. -local surface_docs = { +kelp.surface_docs = { -- entry_id_orig = nodename, _doc_items_entry_name = S("Kelp"), _doc_items_longdesc = S("Kelp grows inside water on top of dirt, sand or gravel."), --_doc_items_create_entry = doc_create, _doc_items_image = "mcl_ocean_kelp_item.png", } -kelp.surface_docs = surface_docs ---[==[-- -register_kelp_surface(surface[, surface_deftemplate[, surface_docs]]) - -surface: table with its specific properties. See also kelp.surface. - -surface_deftemplate: modifiable nodedef template. See also kelp.surface_deftempate. -DO NOT RE-USE THE SAME DEFTEMPLATE. create copies. - -surface_docs: table with properties related to docs. See also kelp.surface_docs. ---]==]-- -local leaf_sounds = mcl_sounds.node_sound_leaves_defaults() -local function register_kelp_surface(surface, surface_deftemplate, surface_docs) +-- Creates new surfaces. +-- NOTE: surface_deftemplate will be modified in-place. +function kelp.register_kelp_surface(surface, surface_deftemplate, surface_docs) local name = surface.name local nodename = surface.nodename - local def = registered_nodes[nodename] + local def = mt_registered_nodes[nodename] local def_tiles = def.tiles local surfacename = "mcl_ocean:kelp_"..name - local surface_deftemplate = surface_deftemplate or kelp.surface_deftemplate -- optional param + local surface_deftemplate = surface_deftemplate or kelp.surface_deftemplate -- Optional param local doc_create = surface.doc_create or false - local surface_docs = surface_docs or kelp.surface_docs + local surface_docs = surface_docs or kelp.surface_docs -- Optional param if doc_create then surface_deftemplate._doc_items_entry_name = surface_docs._doc_items_entry_name surface_deftemplate._doc_items_longdesc = surface_docs._doc_items_longdesc surface_deftemplate._doc_items_create_entry = true surface_deftemplate._doc_items_image = surface_docs._doc_items_image - -- Takes the first surface with docs + -- Sets the first surface as the docs' entry ID if not surface_docs.entry_id_orig then surface_docs.entry_id_orig = nodename end @@ -422,9 +574,9 @@ local function register_kelp_surface(surface, surface_deftemplate, surface_docs) end local sounds = table.copy(def.sounds) - sounds.dig = leaf_sounds.dig - sounds.dug = leaf_sounds.dug - sounds.place = leaf_sounds.place + sounds.dig = kelp.leaf_sounds.dig + sounds.dug = kelp.leaf_sounds.dug + sounds.place = kelp.leaf_sounds.place surface_deftemplate.tiles = surface_deftemplate.tiles or def_tiles surface_deftemplate.inventory_image = surface_deftemplate.inventory_image or "("..def_tiles[1]..")^mcl_ocean_kelp_item.png" @@ -440,9 +592,9 @@ end -- Kelp surfaces nodes --------------------------------------------------------- -- Dirt must be registered first, for the docs -register_kelp_surface(surfaces[1], table.copy(surface_deftemplate), surface_docs) -for i=2, #surfaces do - register_kelp_surface(surfaces[i], table.copy(surface_deftemplate), surface_docs) +kelp.register_kelp_surface(kelp.surfaces[1], table.copy(kelp.surface_deftemplate), kelp.surface_docs) +for i=2, #kelp.surfaces do + kelp.register_kelp_surface(kelp.surfaces[i], table.copy(kelp.surface_deftemplate), kelp.surface_docs) end -- Kelp item ------------------------------------------------------------------- @@ -453,12 +605,12 @@ minetest.register_craftitem("mcl_ocean:kelp", { _doc_items_create_entry = false, inventory_image = "mcl_ocean_kelp_item.png", wield_image = "mcl_ocean_kelp_item.png", - on_place = kelp_on_place, + on_place = kelp.kelp_on_place, groups = { deco_block = 1 }, }) if mod_doc then - doc.add_entry_alias("nodes", surface_docs.entry_id_orig, "craftitems", "mcl_ocean:kelp") + doc.add_entry_alias("nodes", kelp.surface_docs.entry_id_orig, "craftitems", "mcl_ocean:kelp") end -- Dried kelp ------------------------------------------------------------------ @@ -523,26 +675,17 @@ minetest.register_craft({ }) -- ABMs ------------------------------------------------------------------------ -minetest.register_abm({ - label = "Kelp growth", - nodenames = { "group:kelp" }, - interval = 45, - chance = 12, - catch_up = false, - action = grow_kelp, -}) -- NOTE: Uncomment this to use nodetimers minetest.register_lbm({ label = "Kelp timer registration", name = "mcl_ocean:kelp_timer_registration", nodenames = { "group:kelp" }, - run_at_every_load = false, - action = surface_register_nodetimer, + run_at_every_load = true, -- so old kelps are also registered + action = kelp.surface_register_nodetimer, }) -- NOTE: Uncomment this to use ABMs --- Break kelp not underwater. -- minetest.register_abm({ -- label = "Kelp drops", -- nodenames = { "group:kelp" }, @@ -551,3 +694,12 @@ minetest.register_lbm({ -- catch_up = false, -- action = surface_unsubmerged_abm, -- }) +-- +-- minetest.register_abm({ +-- label = "Kelp growth", +-- nodenames = { "group:kelp" }, +-- interval = 45, +-- chance = 12, +-- catch_up = false, +-- action = grow_abm, +-- }) From 1b9737b4312d566cd05768e28cadf0ea386f0c6b Mon Sep 17 00:00:00 2001 From: ArTee3 Date: Mon, 29 Mar 2021 18:13:10 +0200 Subject: [PATCH 064/234] Prevent beds from appearing and disappearing if they cannot be placed, fix #1419 --- mods/ITEMS/mcl_beds/api.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_beds/api.lua b/mods/ITEMS/mcl_beds/api.lua index c274a29a0d..a2df1bdf38 100644 --- a/mods/ITEMS/mcl_beds/api.lua +++ b/mods/ITEMS/mcl_beds/api.lua @@ -89,6 +89,7 @@ function mcl_beds.register_bed(name, def) selection_box = selection_box_bottom, collision_box = collision_box_bottom, drop = "", + node_placement_prediction = "", on_place = function(itemstack, placer, pointed_thing) local under = pointed_thing.under From 5a7d128861e610f41f723d906eead609168f0ce2 Mon Sep 17 00:00:00 2001 From: epCode Date: Mon, 29 Mar 2021 11:29:39 -0700 Subject: [PATCH 065/234] Add wither functions from MC --- .../textures/mobs_mc_wither_half_health.png | Bin 0 -> 1323 bytes mods/ENTITIES/mobs_mc/wither.lua | 10 +++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_half_health.png diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_half_health.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_half_health.png new file mode 100644 index 0000000000000000000000000000000000000000..f6353400cda70d9e14a98ee98082030b9f81f500 GIT binary patch literal 1323 zcmV+`1=RY9P)3llH3nBT`+P)=A*t z;2@1T5QoTB2kwFsV*)AS6b?zWfrwp*wCIY_%e)=U>@V#~ve*yI?wgr?JM-p!@6B4z zLIUjVyCXO*(Cpd%pBXo-g zM4RIRwL0MUfD7M?E5EPRQ8?;NdFA&xv6?tSw|L%XujwZ;#iVA5m8ms2Zoa;yF~B*; z^acp}`TFvLf?rZwVKKmMnBxFt0*cJ)q}DgHMSHg)4M+3|`oOLY9E3t%-;{kcuX+=9 zy{XL_;qjl=bOs3eBG8%od`~WvPkMbbF-016Ixg_~Um^c=4d?=R$7F7xDY2TE=V@X5 zz8wHvN3_-IGF5UNyS7|7wfP=!u?eG&xKyfhc|tpw9N%@!9z&a==m;O~Tk!_aow!UBQ~5}q zp>i?{$P+ky#=3`xkD~6{dJy$Q(;QiUc=#x13{bhK<6{w=c?Y>emYj@ZD2+(+)6vxGyI3+n(SfmsPh@_4IpYe)fBbQMznM1DLp&g^zK3 z*6_=6@;UIN^8cA`u-Hhi&f6`utN zKm3@ifxCFpc)mdGKUqKK8(UZwPy-X&RU^2IYsT9(>;~uzfEy=_>(AM}p?!%E{TfWe=>-pJ**zf5X>W;|58z8R8fcgrq+gYq2IO`IbnV$rwEs-&$O7(d|e|YrN znlA-Rc^;5ENI#11+TwZ;$~Mz3(>WpO95MG85LeqnzZlc6zI@>ap*#qgVue~bmF0{v z_ZTp%5}CPsfZK@fo>H!c`z;K;SE6jK9f*>d&&L>guYmil=vY+`$vW>yQNlKxAXt^i zWGImtjcsLFOH(4V0^bt_k!raMMewAP9*rX}p=Umw;#>KRy(a#APq;ppD^#dZp+bcU h6)IGyP@%%?@judG-R$kK*4Y36002ovPDHLkV1kb7etZA` literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 3fbf65955e..caf5a248d3 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -16,7 +16,7 @@ mobs:register_mob("mobs_mc:wither", { hp_min = 300, xp_min = 50, xp_max = 50, - armor = {undead = 80, fleshy = 80}, + armor = {undead = 80, fleshy = 100}, -- This deviates from MC Wiki's size, which makes no sense collisionbox = {-0.9, 0.4, -0.9, 0.9, 2.45, 0.9}, visual = "mesh", @@ -66,6 +66,14 @@ mobs:register_mob("mobs_mc:wither", { run_start = 0, run_end = 20, }, harmed_by_heal = true, + do_custom = function(self) + if self.health < (self.hp_max / 2) then + self.base_texture = "mobs_mc_wither_half_health.png" + self.fly = false + self.object:set_properties({textures={self.base_texture}}) + self.armor = {undead = 80, fleshy = 80} + end + end, on_spawn = function(self) minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64}) end, From f51deb07375ec7b57eaa18778ae860eefbff0074 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 29 Mar 2021 22:21:14 +0200 Subject: [PATCH 066/234] use propers colors in mcl_jukebox --- mods/ITEMS/mcl_jukebox/init.lua | 4 ++-- mods/ITEMS/mcl_jukebox/mod.conf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_jukebox/init.lua b/mods/ITEMS/mcl_jukebox/init.lua index c5bd3d268e..067848f506 100644 --- a/mods/ITEMS/mcl_jukebox/init.lua +++ b/mods/ITEMS/mcl_jukebox/init.lua @@ -20,8 +20,8 @@ function mcl_jukebox.register_record(title, author, identifier, image, sound) local usagehelp = S("Place a music disc into an empty jukebox to play the music. Use the jukebox again to retrieve the music disc. The music can only be heard by you, not by other players.") minetest.register_craftitem(":mcl_jukebox:record_"..identifier, { description = - core.colorize("#55FFFF", S("Music Disc")) .. "\n" .. - core.colorize("#989898", S("@1—@2", author, title)), + core.colorize(mcl_colors.AQUA, S("Music Disc")) .. "\n" .. + core.colorize(mcl_colors.GRAY, S("@1—@2", author, title)), _doc_items_create_entry = true, _doc_items_entry_name = entryname, _doc_items_longdesc = longdesc, diff --git a/mods/ITEMS/mcl_jukebox/mod.conf b/mods/ITEMS/mcl_jukebox/mod.conf index ad1f8c06a9..9046ff7d32 100644 --- a/mods/ITEMS/mcl_jukebox/mod.conf +++ b/mods/ITEMS/mcl_jukebox/mod.conf @@ -1,3 +1,3 @@ name = mcl_jukebox description = Jukebox and music discs are used to play background music on a per-player basis. -depends = mcl_core, mcl_sounds +depends = mcl_core, mcl_sounds, mcl_colors From a2fcd28a3dcbf1aaa07c9f2c21ba7cd3872b7cd4 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 29 Mar 2021 22:23:00 +0200 Subject: [PATCH 067/234] use proper colors in mcl_skins --- mods/PLAYER/mcl_skins/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/PLAYER/mcl_skins/init.lua b/mods/PLAYER/mcl_skins/init.lua index ac770f8f52..0ecb4a85ab 100644 --- a/mods/PLAYER/mcl_skins/init.lua +++ b/mods/PLAYER/mcl_skins/init.lua @@ -237,7 +237,7 @@ end) mcl_skins.show_formspec = function(playername) local formspec = "size[7,8.5]" - formspec = formspec .. "label[2,2;" .. minetest.formspec_escape(minetest.colorize("#383838", S("Select player skin:"))) .. "]" + formspec = formspec .. "label[2,2;" .. minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Select player skin:"))) .. "]" .. "textlist[0,2.5;6.8,6;skins_set;" local meta @@ -265,7 +265,7 @@ mcl_skins.show_formspec = function(playername) if meta then if meta.name and meta.name ~= "" then - formspec = formspec .. "label[2,0.5;" .. minetest.formspec_escape(minetest.colorize("#383838", S("Name: @1", meta.name))) .. "]" + formspec = formspec .. "label[2,0.5;" .. minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Name: @1", meta.name))) .. "]" end end From f8a627915e17779bec1a52fe867877036c043f72 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 29 Mar 2021 22:57:05 +0200 Subject: [PATCH 068/234] use proper colors in mcl_books --- mods/ITEMS/mcl_books/init.lua | 8 ++++---- mods/ITEMS/mcl_books/mod.conf | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_books/init.lua b/mods/ITEMS/mcl_books/init.lua index 45208c4132..5101994e9d 100644 --- a/mods/ITEMS/mcl_books/init.lua +++ b/mods/ITEMS/mcl_books/init.lua @@ -1,4 +1,4 @@ -local S =minetest.get_translator("mcl_books") +local S = minetest.get_translator("mcl_books") local max_text_length = 4500 -- TODO: Increase to 12800 when scroll bar was added to written book local max_title_length = 64 @@ -67,7 +67,7 @@ local make_description = function(title, author, generation) else desc = S("Tattered Book") end - desc = desc .. "\n" .. minetest.colorize("#AAAAAA", S("by @1", author)) + desc = desc .. "\n" .. minetest.colorize(mcl_colors.GRAY, S("by @1", author)) return desc end @@ -147,8 +147,8 @@ minetest.register_on_player_receive_fields(function ( player, formname, fields ) local formspec = "size[8,9]".. header.. "background[-0.5,-0.5;9,10;mcl_books_book_bg.png]".. - "field[0.75,1;7.25,1;title;"..minetest.formspec_escape(minetest.colorize("#000000", S("Enter book title:")))..";]".. - "label[0.75,1.5;"..minetest.formspec_escape(minetest.colorize("#404040", S("by @1", name))).."]".. + "field[0.75,1;7.25,1;title;"..minetest.formspec_escape(minetest.colorize(mcl_colors.BLACK, S("Enter book title:")))..";]".. + "label[0.75,1.5;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("by @1", name))).."]".. "button_exit[0.75,7.95;3,1;sign;"..minetest.formspec_escape(S("Sign and Close")).."]".. "tooltip[sign;"..minetest.formspec_escape(S("Note: The book will no longer be editable after signing")).."]".. "button[4.25,7.95;3,1;cancel;"..minetest.formspec_escape(S("Cancel")).."]" diff --git a/mods/ITEMS/mcl_books/mod.conf b/mods/ITEMS/mcl_books/mod.conf index 7c4513b00c..cea9a5dd8d 100644 --- a/mods/ITEMS/mcl_books/mod.conf +++ b/mods/ITEMS/mcl_books/mod.conf @@ -1,4 +1,4 @@ name = mcl_books author = celeron55 description = Books mod for MCL2 -optional_depends = mcl_init, mcl_core, mcl_sounds, mcl_mobitems, mcl_dye +optional_depends = mcl_init, mcl_core, mcl_sounds, mcl_mobitems, mcl_dye, mcl_colors From 84819bf9f5164ab208b7be1e94d142906359a1af Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:01:29 +0200 Subject: [PATCH 069/234] MAKE EVERY SINGLE MOD USE PROPER COLORS!!! --- mods/ENTITIES/mobs_mc/1_items_default.lua | 2 +- mods/ENTITIES/mobs_mc/mod.conf | 2 +- mods/ENTITIES/mobs_mc/villager.lua | 2 +- mods/HELP/doc/doc/init.lua | 18 ++++++----------- mods/HELP/doc/doc/mod.conf | 1 + mods/HELP/mcl_craftguide/init.lua | 8 ++++---- mods/HELP/mcl_craftguide/mod.conf | 2 +- mods/HELP/mcl_tt/mod.conf | 2 +- mods/HELP/mcl_tt/snippets_mcl.lua | 2 +- mods/HELP/tt/init.lua | 8 ++++---- mods/HELP/tt/mod.conf | 1 + mods/HUD/awards/api.lua | 6 +++--- mods/HUD/awards/mod.conf | 1 + mods/HUD/mcl_inventory/creative.lua | 2 +- mods/HUD/mcl_inventory/init.lua | 4 ++-- mods/HUD/mcl_inventory/mod.conf | 2 +- mods/ITEMS/REDSTONE/mcl_dispensers/init.lua | 4 ++-- mods/ITEMS/REDSTONE/mcl_dispensers/mod.conf | 2 +- mods/ITEMS/REDSTONE/mcl_droppers/init.lua | 4 ++-- mods/ITEMS/REDSTONE/mcl_droppers/init_new.lua | 4 ++-- mods/ITEMS/REDSTONE/mcl_droppers/mod.conf | 2 +- mods/ITEMS/mcl_anvils/init.lua | 4 ++-- mods/ITEMS/mcl_anvils/mod.conf | 2 +- mods/ITEMS/mcl_banners/mod.conf | 1 + mods/ITEMS/mcl_banners/patterncraft.lua | 2 +- mods/ITEMS/mcl_brewing/init.lua | 8 ++++---- mods/ITEMS/mcl_brewing/mod.conf | 2 +- mods/ITEMS/mcl_chests/init.lua | 20 +++++++++---------- mods/ITEMS/mcl_chests/mod.conf | 2 +- mods/ITEMS/mcl_core/mod.conf | 2 +- mods/ITEMS/mcl_core/nodes_cactuscane.lua | 2 +- mods/ITEMS/mcl_core/nodes_misc.lua | 4 ++-- mods/ITEMS/mcl_crafting_table/init.lua | 4 ++-- mods/ITEMS/mcl_crafting_table/mod.conf | 3 +-- mods/ITEMS/mcl_enchanting/engine.lua | 10 +++++----- mods/ITEMS/mcl_enchanting/mod.conf | 2 +- mods/ITEMS/mcl_farming/mod.conf | 2 +- mods/ITEMS/mcl_farming/potatoes.lua | 2 +- mods/ITEMS/mcl_furnaces/init.lua | 8 ++++---- mods/ITEMS/mcl_furnaces/mod.conf | 2 +- mods/ITEMS/mcl_hoppers/init.lua | 4 ++-- mods/ITEMS/mcl_hoppers/mod.conf | 2 +- mods/ITEMS/mcl_mobitems/init.lua | 8 ++++---- mods/ITEMS/mcl_mobitems/mod.conf | 2 +- mods/ITEMS/mcl_nether/init.lua | 2 +- mods/ITEMS/mcl_nether/mod.conf | 2 +- 46 files changed, 89 insertions(+), 92 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/1_items_default.lua b/mods/ENTITIES/mobs_mc/1_items_default.lua index ddcc290c73..b4abd4f9cc 100644 --- a/mods/ENTITIES/mobs_mc/1_items_default.lua +++ b/mods/ENTITIES/mobs_mc/1_items_default.lua @@ -521,7 +521,7 @@ if c("totem") then -- Totem of Undying minetest.register_craftitem("mobs_mc:totem", { description = S("Totem of Undying"), - _tt_help = minetest.colorize("#00FF00", S("Protects you from death while wielding it")), + _tt_help = minetest.colorize(mcl_colors.GREEN, S("Protects you from death while wielding it")), _doc_items_longdesc = S("A totem of undying is a rare artifact which may safe you from certain death."), _doc_items_usagehelp = S("The totem only works while you hold it in your hand. If you receive fatal damage, you are saved from death and you get a second chance with 1 HP. The totem is destroyed in the process, however."), inventory_image = "mcl_totems_totem.png", diff --git a/mods/ENTITIES/mobs_mc/mod.conf b/mods/ENTITIES/mobs_mc/mod.conf index 98f48b388a..a3057faff9 100644 --- a/mods/ENTITIES/mobs_mc/mod.conf +++ b/mods/ENTITIES/mobs_mc/mod.conf @@ -1,6 +1,6 @@ name = mobs_mc author = maikerumine description = Adds Minecraft-like monsters and animals. -depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip +depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_colors optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, mobs_mc_gameconfig, doc_items diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 9429a691be..68644266f4 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -516,7 +516,7 @@ local function show_trade_formspec(playername, trader, tradenum) "size[9,8.75]" .."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]" ..disabled_img - .."label[4,0;"..F(minetest.colorize("#313131", S(profession))).."]" + .."label[4,0;"..F(minetest.colorize(mcl_colors.DARK_GRAY, S(profession))).."]" .."list[current_player;main;0,4.5;9,3;9]" .."list[current_player;main;0,7.74;9,1;]" ..b_prev..b_next diff --git a/mods/HELP/doc/doc/init.lua b/mods/HELP/doc/doc/init.lua index 360cc149cd..9057cda8e4 100644 --- a/mods/HELP/doc/doc/init.lua +++ b/mods/HELP/doc/doc/init.lua @@ -1,13 +1,7 @@ local S = minetest.get_translator("doc") local F = function(f) return minetest.formspec_escape(S(f)) end --- Compability for 0.4.14 or earlier -local colorize -if minetest.colorize then - colorize = minetest.colorize -else - colorize = function(color, text) return text end -end +local colorize = minetest.colorize doc = {} @@ -41,10 +35,10 @@ doc.FORMSPEC.ENTRY_HEIGHT = doc.FORMSPEC.ENTRY_END_Y - doc.FORMSPEC.ENTRY_START_ -- Internal helper variables local DOC_INTRO = S("This is the help.") -local COLOR_NOT_VIEWED = "#00FFFF" -- cyan -local COLOR_VIEWED = "#FFFFFF" -- white -local COLOR_HIDDEN = "#999999" -- gray -local COLOR_ERROR = "#FF0000" -- red +local COLOR_NOT_VIEWED = mcl_colors.AQUA +local COLOR_VIEWED = mcl_colors.WHITE +local COLOR_HIDDEN = mcl_colors.GRAY +local COLOR_ERROR = mcl_colors.RED local CATEGORYFIELDSIZE = { WIDTH = math.ceil(doc.FORMSPEC.WIDTH / 4), @@ -776,7 +770,7 @@ function doc.generate_entry_list(cid, playername) if name == nil or name == "" then name = S("Nameless entry (@1)", eid) if doc.entry_viewed(playername, cid, eid) then - viewedprefix = "#FF4444" + viewedprefix = mcl_colors.RED else viewedprefix = COLOR_ERROR end diff --git a/mods/HELP/doc/doc/mod.conf b/mods/HELP/doc/doc/mod.conf index 0f65ddff7e..54064551bb 100644 --- a/mods/HELP/doc/doc/mod.conf +++ b/mods/HELP/doc/doc/mod.conf @@ -2,3 +2,4 @@ name = doc author = Wuzzy description = A simple in-game documentation system which enables mods to add help entries based on templates. optional_depends = unified_inventory, sfinv_buttons, central_message, inventory_plus +depends = mcl_colors diff --git a/mods/HELP/mcl_craftguide/init.lua b/mods/HELP/mcl_craftguide/init.lua index eb98bcce08..829fc41817 100644 --- a/mods/HELP/mcl_craftguide/init.lua +++ b/mods/HELP/mcl_craftguide/init.lua @@ -410,7 +410,7 @@ local function get_tooltip(item, groups, cooktime, burntime) local tooltip if groups then - local gcol = "#FFAAFF" + local gcol = mcl_colors.LIGHT_PURPLE if #groups == 1 then local g = group_names[groups[1]] local groupstr @@ -446,12 +446,12 @@ local function get_tooltip(item, groups, cooktime, burntime) if not groups and cooktime then tooltip = tooltip .. "\n" .. - S("Cooking time: @1", colorize("yellow", cooktime)) + S("Cooking time: @1", colorize(mcl_colors.YELLOW, cooktime)) end if not groups and burntime then tooltip = tooltip .. "\n" .. - S("Burning time: @1", colorize("yellow", burntime)) + S("Burning time: @1", colorize(mcl_colors.YELLOW, burntime)) end return fmt(FMT.tooltip, item, ESC(tooltip)) @@ -668,7 +668,7 @@ local function make_formspec(name) fs[#fs + 1] = fmt("label[%f,%f;%s]", sfinv_only and 6.3 or data.iX - 2.2, 0.22, - ESC(colorize("#383838", fmt("%s / %u", data.pagenum, data.pagemax)))) + ESC(colorize(mcl_colors.DARK_GRAY, fmt("%s / %u", data.pagenum, data.pagemax)))) fs[#fs + 1] = fmt([[ image_button[%f,0.12;0.8,0.8;craftguide_prev_icon.png;prev;] diff --git a/mods/HELP/mcl_craftguide/mod.conf b/mods/HELP/mcl_craftguide/mod.conf index b7ab8882c5..ce99c0e32e 100644 --- a/mods/HELP/mcl_craftguide/mod.conf +++ b/mods/HELP/mcl_craftguide/mod.conf @@ -1,5 +1,5 @@ name = mcl_craftguide author = kilbith description = The most comprehensive Crafting Guide on Minetest. -depends = mcl_core, mcl_compass, mcl_clock, doc +depends = mcl_core, mcl_compass, mcl_clock, doc, mcl_colors optional_depends = sfinv, sfinv_buttons diff --git a/mods/HELP/mcl_tt/mod.conf b/mods/HELP/mcl_tt/mod.conf index 3a33b70dc8..e442e13207 100644 --- a/mods/HELP/mcl_tt/mod.conf +++ b/mods/HELP/mcl_tt/mod.conf @@ -1,4 +1,4 @@ name = mcl_tt author = Wuzzy description = Add MCL2 tooltips -depends = tt, mcl_enchanting +depends = tt, mcl_enchanting, mcl_colors diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 6e28035020..3d13df7510 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -77,7 +77,7 @@ end) tt.register_snippet(function(itemstring) local def = minetest.registered_items[itemstring] if minetest.get_item_group(itemstring, "crush_after_fall") == 1 then - return S("Deals damage when falling"), "#FFFF00" + return S("Deals damage when falling"), mcl_colors.YELLOW end end) diff --git a/mods/HELP/tt/init.lua b/mods/HELP/tt/init.lua index 88dbc7165b..afc421e4f5 100644 --- a/mods/HELP/tt/init.lua +++ b/mods/HELP/tt/init.lua @@ -1,8 +1,8 @@ tt = {} -tt.COLOR_DEFAULT = "#d0ffd0" -tt.COLOR_DANGER = "#ffff00" -tt.COLOR_GOOD = "#00ff00" -tt.NAME_COLOR = "#FFFF4C" +tt.COLOR_DEFAULT = mcl_colors.GREEN +tt.COLOR_DANGER = mcl_colors.YELLOW +tt.COLOR_GOOD = mcl_colors.GREEN +tt.NAME_COLOR = mcl_colors.YELLOW -- API tt.registered_snippets = {} diff --git a/mods/HELP/tt/mod.conf b/mods/HELP/tt/mod.conf index 23ce15369c..2a260772d3 100644 --- a/mods/HELP/tt/mod.conf +++ b/mods/HELP/tt/mod.conf @@ -1,3 +1,4 @@ name = tt author = Wuzzy description = Support for custom tooltip extensions for items +depends = mcl_colors diff --git a/mods/HUD/awards/api.lua b/mods/HUD/awards/api.lua index 9b0261b65c..6601dd6265 100644 --- a/mods/HUD/awards/api.lua +++ b/mods/HUD/awards/api.lua @@ -214,7 +214,7 @@ function awards.unlock(name, award) -- Get award minetest.log("action", name.." has gotten award "..award) - minetest.chat_send_all(S("@1 has made the achievement @2", name, minetest.colorize("#51EF4E", "[" .. (awdef.title or award) .. "]"))) + minetest.chat_send_all(S("@1 has made the achievement @2", name, minetest.colorize(mcl_colors.GREEN, "[" .. (awdef.title or award) .. "]"))) data.unlocked[award] = award awards.save() @@ -447,7 +447,7 @@ function awards.getFormspec(name, to, sid) first = false if def.secret and not award.got then - formspec = formspec .. "#707070"..minetest.formspec_escape(S("(Secret Award)")) + formspec = formspec .. mcl_colors.DARK_GRAY..minetest.formspec_escape(S("(Secret Award)")) else local title = award.name if def and def.title then @@ -456,7 +456,7 @@ function awards.getFormspec(name, to, sid) if award.got then formspec = formspec .. minetest.formspec_escape(title) else - formspec = formspec .. "#ACACAC".. minetest.formspec_escape(title) + formspec = formspec .. mcl_colors.GRAY.. minetest.formspec_escape(title) end end end diff --git a/mods/HUD/awards/mod.conf b/mods/HUD/awards/mod.conf index 8b15346922..1657323e2d 100644 --- a/mods/HUD/awards/mod.conf +++ b/mods/HUD/awards/mod.conf @@ -6,3 +6,4 @@ license = LGPL 2.1 or later forum = https://forum.minetest.net/viewtopic.php?t=4870 version = 2.3.0 optional_depends = sfinv, unified_inventory +depends = mcl_colors diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index b3ee40bf7f..a69fcef5be 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -442,7 +442,7 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz end local caption = "" if name ~= "inv" and filtername[name] then - caption = "label[0,1.2;"..F(minetest.colorize("#313131", filtername[name])).."]" + caption = "label[0,1.2;"..F(minetest.colorize(mcl_colors.DARK_GRAY, filtername[name])).."]" end formspec = "size[10,9.3]".. diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index 0544240515..e9da9486e7 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -109,10 +109,10 @@ local function set_inventory(player, armor_change_only) mcl_formspec.get_itemslot_bg(0,3,1,1).. armor_slot_imgs.. -- craft and inventory - "label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4;"..F(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. "list[current_player;main;0,7.74;9,1;]".. - "label[4,0.5;"..F(minetest.colorize("#313131", S("Crafting"))).."]".. + "label[4,0.5;"..F(minetest.colorize(mcl_colors.DARK_GRAY, S("Crafting"))).."]".. "list[current_player;craft;4,1;2,2]".. "list[current_player;craftpreview;7,1.5;1,1;]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. diff --git a/mods/HUD/mcl_inventory/mod.conf b/mods/HUD/mcl_inventory/mod.conf index fa6b2c2f46..edd6343c7b 100644 --- a/mods/HUD/mcl_inventory/mod.conf +++ b/mods/HUD/mcl_inventory/mod.conf @@ -1,6 +1,6 @@ name = mcl_inventory author = BlockMen description = Adds the player inventory and creative inventory. -depends = mcl_init, mcl_formspec +depends = mcl_init, mcl_formspec, mcl_colors optional_depends = mcl_player, _mcl_autogroup, mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting diff --git a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua index b6d0d2ef69..1fd63cb4d5 100644 --- a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua @@ -13,12 +13,12 @@ local S = minetest.get_translator("mcl_dispensers") local setup_dispenser = function(pos) -- Set formspec and inventory local form = "size[9,8.75]".. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. mcl_formspec.get_itemslot_bg(0,7.74,9,1).. - "label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dispenser"))).."]".. + "label[3,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Dispenser"))).."]".. "list[current_name;main;3,0.5;3,3;]".. mcl_formspec.get_itemslot_bg(3,0.5,3,3).. "listring[current_name;main]".. diff --git a/mods/ITEMS/REDSTONE/mcl_dispensers/mod.conf b/mods/ITEMS/REDSTONE/mcl_dispensers/mod.conf index 13cdb5f5a5..ac1b56c7d9 100644 --- a/mods/ITEMS/REDSTONE/mcl_dispensers/mod.conf +++ b/mods/ITEMS/REDSTONE/mcl_dispensers/mod.conf @@ -1,3 +1,3 @@ name = mcl_dispensers -depends = mcl_init, mcl_formspec, mesecons, mcl_sounds, mcl_tnt, mcl_worlds, mcl_core, mcl_nether, mcl_armor_stand, mcl_armor +depends = mcl_init, mcl_formspec, mesecons, mcl_sounds, mcl_tnt, mcl_worlds, mcl_core, mcl_nether, mcl_armor_stand, mcl_armor, mcl_colors optional_depends = doc, screwdriver diff --git a/mods/ITEMS/REDSTONE/mcl_droppers/init.lua b/mods/ITEMS/REDSTONE/mcl_droppers/init.lua index 715a85f3d7..0d41c3552a 100644 --- a/mods/ITEMS/REDSTONE/mcl_droppers/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_droppers/init.lua @@ -14,12 +14,12 @@ local S = minetest.get_translator("mcl_droppers") local setup_dropper = function(pos) -- Set formspec and inventory local form = "size[9,8.75]".. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. mcl_formspec.get_itemslot_bg(0,7.74,9,1).. - "label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dropper"))).."]".. + "label[3,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Dropper"))).."]".. "list[current_name;main;3,0.5;3,3;]".. mcl_formspec.get_itemslot_bg(3,0.5,3,3).. "listring[current_name;main]".. diff --git a/mods/ITEMS/REDSTONE/mcl_droppers/init_new.lua b/mods/ITEMS/REDSTONE/mcl_droppers/init_new.lua index 1bf968a825..b41d9c2fee 100644 --- a/mods/ITEMS/REDSTONE/mcl_droppers/init_new.lua +++ b/mods/ITEMS/REDSTONE/mcl_droppers/init_new.lua @@ -15,10 +15,10 @@ local setup_dropper = function(pos) -- Set formspec and inventory local form = "size[9,8.75]".. "background[-0.19,-0.25;9.41,9.49;crafting_inventory_9_slots.png]".. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. "list[current_player;main;0,7.74;9,1;]".. - "label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dropper"))).."]".. + "label[3,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Dropper"))).."]".. "list[current_name;main;3,0.5;3,3;]".. "listring[current_name;main]".. "listring[current_player;main]" diff --git a/mods/ITEMS/REDSTONE/mcl_droppers/mod.conf b/mods/ITEMS/REDSTONE/mcl_droppers/mod.conf index bbb1c19f24..b5cf8f0b71 100644 --- a/mods/ITEMS/REDSTONE/mcl_droppers/mod.conf +++ b/mods/ITEMS/REDSTONE/mcl_droppers/mod.conf @@ -1,3 +1,3 @@ name = mcl_droppers -depends = mcl_init, mcl_formspec, mesecons, mcl_util +depends = mcl_init, mcl_formspec, mesecons, mcl_util, mcl_colors optional_depends = doc, screwdriver diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index c3c238e7f9..1845ed7767 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -16,7 +16,7 @@ local function get_anvil_formspec(set_name) end return "size[9,8.75]".. "background[-0.19,-0.25;9.41,9.49;mcl_anvils_inventory.png]".. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. @@ -27,7 +27,7 @@ local function get_anvil_formspec(set_name) mcl_formspec.get_itemslot_bg(4,2.5,1,1).. "list[context;output;8,2.5;1,1;]".. mcl_formspec.get_itemslot_bg(8,2.5,1,1).. - "label[3,0.1;"..minetest.formspec_escape(minetest.colorize("#313131", S("Repair and Name"))).."]".. + "label[3,0.1;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Repair and Name"))).."]".. "field[3.25,1;4,1;name;;"..minetest.formspec_escape(set_name).."]".. "field_close_on_enter[name;false]".. "button[7,0.7;2,1;name_button;"..minetest.formspec_escape(S("Set Name")).."]".. diff --git a/mods/ITEMS/mcl_anvils/mod.conf b/mods/ITEMS/mcl_anvils/mod.conf index cd4fa02a83..cbb5dc2231 100644 --- a/mods/ITEMS/mcl_anvils/mod.conf +++ b/mods/ITEMS/mcl_anvils/mod.conf @@ -1,5 +1,5 @@ name = mcl_anvils author = Wuzzy description = Anvils mods for MCL2 -depends = mcl_init, mcl_formspec, mcl_sounds, tt, mcl_enchanting +depends = mcl_init, mcl_formspec, mcl_sounds, tt, mcl_enchanting, mcl_colors optional_depends = mcl_core, screwdriver diff --git a/mods/ITEMS/mcl_banners/mod.conf b/mods/ITEMS/mcl_banners/mod.conf index cee7bace71..8c3117206c 100644 --- a/mods/ITEMS/mcl_banners/mod.conf +++ b/mods/ITEMS/mcl_banners/mod.conf @@ -1,4 +1,5 @@ name = mcl_banners author = 22i description = Adds decorative banners in different colors which can be emblazoned with patterns, offering a countless number of combinations. +depends = mcl_colors optional_depends = mcl_sounds, mcl_core, mcl_wool, mcl_cauldrons, doc, screwdriver diff --git a/mods/ITEMS/mcl_banners/patterncraft.lua b/mods/ITEMS/mcl_banners/patterncraft.lua index e1f05ff11b..31782a42b8 100644 --- a/mods/ITEMS/mcl_banners/patterncraft.lua +++ b/mods/ITEMS/mcl_banners/patterncraft.lua @@ -281,7 +281,7 @@ mcl_banners.make_advanced_banner_description = function(description, layers) -- Final string concatenations: Just a list of strings local append = table.concat(layerstrings, "\n") - description = description .. "\n" .. minetest.colorize("#8F8F8F", append) + description = description .. "\n" .. minetest.colorize(mcl_colors.GRAY, append) return description end end diff --git a/mods/ITEMS/mcl_brewing/init.lua b/mods/ITEMS/mcl_brewing/init.lua index 617929ff73..78ccd8ed9f 100644 --- a/mods/ITEMS/mcl_brewing/init.lua +++ b/mods/ITEMS/mcl_brewing/init.lua @@ -4,8 +4,8 @@ local function active_brewing_formspec(fuel_percent, brew_percent) return "size[9,8.75]".. "background[-0.19,-0.25;9.5,9.5;mcl_brewing_inventory.png]".. - "label[4,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Brewing Stand"))).."]".. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[4,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Brewing Stand"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.75;9,1;]".. @@ -35,8 +35,8 @@ end local brewing_formspec = "size[9,8.75]".. "background[-0.19,-0.25;9.5,9.5;mcl_brewing_inventory.png]".. - "label[4,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Brewing Stand"))).."]".. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[4,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Brewing Stand"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.75;9,1;]".. diff --git a/mods/ITEMS/mcl_brewing/mod.conf b/mods/ITEMS/mcl_brewing/mod.conf index 2c27c979e7..160319c936 100644 --- a/mods/ITEMS/mcl_brewing/mod.conf +++ b/mods/ITEMS/mcl_brewing/mod.conf @@ -1,4 +1,4 @@ name = mcl_brewing author = bzoss -depends = mcl_init, mcl_formspec, mcl_sounds, mcl_potions, mcl_mobitems +depends = mcl_init, mcl_formspec, mcl_sounds, mcl_potions, mcl_mobitems, mcl_colors optional_depends = mcl_core, doc, screwdriver diff --git a/mods/ITEMS/mcl_chests/init.lua b/mods/ITEMS/mcl_chests/init.lua index fb8c59f285..1f3f518a49 100644 --- a/mods/ITEMS/mcl_chests/init.lua +++ b/mods/ITEMS/mcl_chests/init.lua @@ -475,10 +475,10 @@ minetest.register_node(small_name, { minetest.show_formspec(clicker:get_player_name(), "mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z, "size[9,8.75]".. - "label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]".. + "label[0,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, name)).."]".. "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]".. mcl_formspec.get_itemslot_bg(0,0.5,9,3).. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. @@ -624,12 +624,12 @@ minetest.register_node(left_name, { minetest.show_formspec(clicker:get_player_name(), "mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z, "size[9,11.5]".. - "label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]".. + "label[0,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, name)).."]".. "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]".. mcl_formspec.get_itemslot_bg(0,0.5,9,3).. "list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,3.5;9,3;]".. mcl_formspec.get_itemslot_bg(0,3.5,9,3).. - "label[0,7;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,7;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,7.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,7.5,9,3).. "list[current_player;main;0,10.75;9,1;]".. @@ -773,12 +773,12 @@ minetest.register_node("mcl_chests:"..basename.."_right", { "mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z, "size[9,11.5]".. - "label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]".. + "label[0,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, name)).."]".. "list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,0.5;9,3;]".. mcl_formspec.get_itemslot_bg(0,0.5,9,3).. "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,3.5;9,3;]".. mcl_formspec.get_itemslot_bg(0,3.5,9,3).. - "label[0,7;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,7;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,7.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,7.5,9,3).. "list[current_player;main;0,10.75;9,1;]".. @@ -986,10 +986,10 @@ minetest.register_node("mcl_chests:ender_chest", { }) local formspec_ender_chest = "size[9,8.75]".. - "label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Ender Chest"))).."]".. + "label[0,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Ender Chest"))).."]".. "list[current_player;enderchest;0,0.5;9,3;]".. mcl_formspec.get_itemslot_bg(0,0.5,9,3).. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. @@ -1104,10 +1104,10 @@ local function formspec_shulker_box(name) name = S("Shulker Box") end return "size[9,8.75]".. - "label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", name)).."]".. + "label[0,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, name)).."]".. "list[current_name;main;0,0.5;9,3;]".. mcl_formspec.get_itemslot_bg(0,0.5,9,3).. - "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. diff --git a/mods/ITEMS/mcl_chests/mod.conf b/mods/ITEMS/mcl_chests/mod.conf index 0ff5129ca2..609b1fff98 100644 --- a/mods/ITEMS/mcl_chests/mod.conf +++ b/mods/ITEMS/mcl_chests/mod.conf @@ -1,3 +1,3 @@ name = mcl_chests -depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_end, mesecons +depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_end, mesecons, mcl_colors optional_depends = doc, screwdriver diff --git a/mods/ITEMS/mcl_core/mod.conf b/mods/ITEMS/mcl_core/mod.conf index e204ace84c..45018df75e 100644 --- a/mods/ITEMS/mcl_core/mod.conf +++ b/mods/ITEMS/mcl_core/mod.conf @@ -1,4 +1,4 @@ name = mcl_core description = Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else. -depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting +depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting, mcl_colors optional_depends = doc diff --git a/mods/ITEMS/mcl_core/nodes_cactuscane.lua b/mods/ITEMS/mcl_core/nodes_cactuscane.lua index d1bcac011e..4ec0051708 100644 --- a/mods/ITEMS/mcl_core/nodes_cactuscane.lua +++ b/mods/ITEMS/mcl_core/nodes_cactuscane.lua @@ -4,7 +4,7 @@ local S = minetest.get_translator("mcl_core") minetest.register_node("mcl_core:cactus", { description = S("Cactus"), - _tt_help = S("Grows on sand").."\n"..minetest.colorize("#FFFF00", S("Contact damage: @1 per half second", 1)), + _tt_help = S("Grows on sand").."\n"..minetest.colorize(mcl_colors.YELLOW, S("Contact damage: @1 per half second", 1)), _doc_items_longdesc = S("This is a piece of cactus commonly found in dry areas, especially deserts. Over time, cacti will grow up to 3 blocks high on sand or red sand. A cactus hurts living beings touching it with a damage of 1 HP every half second. When a cactus block is broken, all cactus blocks connected above it will break as well."), _doc_items_usagehelp = S("A cactus can only be placed on top of another cactus or any sand."), drawtype = "nodebox", diff --git a/mods/ITEMS/mcl_core/nodes_misc.lua b/mods/ITEMS/mcl_core/nodes_misc.lua index 083aa0b85c..8b36f06963 100644 --- a/mods/ITEMS/mcl_core/nodes_misc.lua +++ b/mods/ITEMS/mcl_core/nodes_misc.lua @@ -236,7 +236,7 @@ minetest.register_node("mcl_core:realm_barrier", { -- Prevent placement to protect player from screwing up the world, because the node is not pointable and hard to get rid of. node_placement_prediction = "", on_place = function(pos, placer, itemstack, pointed_thing) - minetest.chat_send_player(placer:get_player_name(), minetest.colorize("#FF0000", "You can't just place a realm barrier by hand!")) + minetest.chat_send_player(placer:get_player_name(), minetest.colorize(mcl_colors.RED, "You can't just place a realm barrier by hand!")) return end, }) @@ -266,7 +266,7 @@ minetest.register_node("mcl_core:void", { -- Prevent placement to protect player from screwing up the world, because the node is not pointable and hard to get rid of. node_placement_prediction = "", on_place = function(pos, placer, itemstack, pointed_thing) - minetest.chat_send_player(placer:get_player_name(), minetest.colorize("#FF0000", "You can't just place the void by hand!")) + minetest.chat_send_player(placer:get_player_name(), minetest.colorize(mcl_colors.RED, "You can't just place the void by hand!")) return end, drop = "", diff --git a/mods/ITEMS/mcl_crafting_table/init.lua b/mods/ITEMS/mcl_crafting_table/init.lua index 4ad581774e..6df4c2544e 100644 --- a/mods/ITEMS/mcl_crafting_table/init.lua +++ b/mods/ITEMS/mcl_crafting_table/init.lua @@ -2,7 +2,7 @@ local S = minetest.get_translator("mcl_crafting_table") local formspec_escape = minetest.formspec_escape local show_formspec = minetest.show_formspec local C = minetest.colorize -local text_color = mcl_colors.BLACK or "#313131" +local text_color = mcl_colors.DARK_GRAY local itemslot_bg = mcl_formspec.get_itemslot_bg mcl_crafting_table = {} @@ -13,7 +13,7 @@ function mcl_crafting_table.show_crafting_form(player) show_formspec(player:get_player_name(), "main", "size[9,8.75]".. "image[4.7,1.5;1.5,1;gui_crafting_arrow.png]".. - "label[0,4;"..formspec_escape(C(text_color, S("Inventory"))).."]".. --"#313131" + "label[0,4;"..formspec_escape(C(text_color, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. diff --git a/mods/ITEMS/mcl_crafting_table/mod.conf b/mods/ITEMS/mcl_crafting_table/mod.conf index 03b3174ab1..149d1c9824 100644 --- a/mods/ITEMS/mcl_crafting_table/mod.conf +++ b/mods/ITEMS/mcl_crafting_table/mod.conf @@ -1,4 +1,3 @@ name = mcl_crafting_table description = Adds a crafting table. -depends = mcl_init, mcl_formspec, mcl_sounds -optional_depends = mcl_colors +depends = mcl_init, mcl_formspec, mcl_sounds, mcl_colors diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index ce6e3543a9..ea69d1868b 100644 --- a/mods/ITEMS/mcl_enchanting/engine.lua +++ b/mods/ITEMS/mcl_enchanting/engine.lua @@ -52,7 +52,7 @@ function mcl_enchanting.get_enchantment_description(enchantment, level) end function mcl_enchanting.get_colorized_enchantment_description(enchantment, level) - return minetest.colorize(mcl_enchanting.enchantments[enchantment].curse and "#FC5454" or "#A8A8A8", mcl_enchanting.get_enchantment_description(enchantment, level)) + return minetest.colorize(mcl_enchanting.enchantments[enchantment].curse and mcl_colors.RED or mcl_colors.GRAY, mcl_enchanting.get_enchantment_description(enchantment, level)) end function mcl_enchanting.get_enchanted_itemstring(itemname) @@ -468,13 +468,13 @@ function mcl_enchanting.show_enchanting_formspec(player) local formspec = "" .. "size[9.07,8.6;]" .. "formspec_version[3]" - .. "label[0,0;" .. C("#313131") .. F(table_name) .. "]" + .. "label[0,0;" .. C(mcl_colors.DARK_GRAY) .. F(table_name) .. "]" .. mcl_formspec.get_itemslot_bg(0.2, 2.4, 1, 1) .. "list[current_player;enchanting_item;0.2,2.4;1,1]" .. mcl_formspec.get_itemslot_bg(1.1, 2.4, 1, 1) .. "image[1.1,2.4;1,1;mcl_enchanting_lapis_background.png]" .. "list[current_player;enchanting_lapis;1.1,2.4;1,1]" - .. "label[0,4;" .. C("#313131") .. F(S("Inventory")).."]" + .. "label[0,4;" .. C(mcl_colors.DARK_GRAY) .. F(S("Inventory")).."]" .. mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3) .. mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1) .. "list[current_player;main;0,4.5;9,3;9]" @@ -501,11 +501,11 @@ function mcl_enchanting.show_enchanting_formspec(player) local hover_ending = (can_enchant and "_hovered" or "_off") formspec = formspec .. "container[3.2," .. y .. "]" - .. (slot and "tooltip[button_" .. i .. ";" .. C("#818181") .. F(slot.description) .. " " .. C("#FFFFFF") .. " . . . ?\n\n" .. (enough_levels and C(enough_lapis and "#818181" or "#FC5454") .. F(S("@1 Lapis Lazuli", i)) .. "\n" .. C("#818181") .. F(S("@1 Enchantment Levels", i)) or C("#FC5454") .. F(S("Level requirement: @1", slot.level_requirement))) .. "]" or "") + .. (slot and "tooltip[button_" .. i .. ";" .. C(mcl_colors.GRAY) .. F(slot.description) .. " " .. C(mcl_colors.WHITE) .. " . . . ?\n\n" .. (enough_levels and C(enough_lapis and mcl_colors.GRAY or mcl_colors.RED) .. F(S("@1 Lapis Lazuli", i)) .. "\n" .. C(mcl_colors.GRAY) .. F(S("@1 Enchantment Levels", i)) or C(mcl_colors.RED) .. F(S("Level requirement: @1", slot.level_requirement))) .. "]" or "") .. "style[button_" .. i .. ";bgimg=mcl_enchanting_button" .. ending .. ".png;bgimg_hovered=mcl_enchanting_button" .. hover_ending .. ".png;bgimg_pressed=mcl_enchanting_button" .. hover_ending .. ".png]" .. "button[0,0;7.5,1.3;button_" .. i .. ";]" .. (slot and "image[0,0;1.3,1.3;mcl_enchanting_number_" .. i .. ending .. ".png]" or "") - .. (slot and "label[7.2,1.1;" .. C(can_enchant and "#80FF20" or "#407F10") .. slot.level_requirement .. "]" or "") + .. (slot and "label[7.2,1.1;" .. C(can_enchant and mcl_colors.GREEN or mcl_colors.DARK_GREEN) .. slot.level_requirement .. "]" or "") .. (slot and slot.glyphs or "") .. "container_end[]" y = y + 1.35 diff --git a/mods/ITEMS/mcl_enchanting/mod.conf b/mods/ITEMS/mcl_enchanting/mod.conf index ac4dad644b..4d4741fb83 100644 --- a/mods/ITEMS/mcl_enchanting/mod.conf +++ b/mods/ITEMS/mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting description = Enchanting for MineClone2 -depends = tt, walkover, mcl_sounds +depends = tt, walkover, mcl_sounds, mcl_colors optional_depends = screwdriver author = Fleckenstein diff --git a/mods/ITEMS/mcl_farming/mod.conf b/mods/ITEMS/mcl_farming/mod.conf index 73627923e9..9ab36c39f1 100644 --- a/mods/ITEMS/mcl_farming/mod.conf +++ b/mods/ITEMS/mcl_farming/mod.conf @@ -1,3 +1,3 @@ name = mcl_farming -depends = mcl_core, mcl_sounds, mcl_wool, mcl_torches, mcl_weather, mobs_mc +depends = mcl_core, mcl_sounds, mcl_wool, mcl_torches, mcl_weather, mobs_mc, mcl_colors optional_depends = mcl_armor, doc diff --git a/mods/ITEMS/mcl_farming/potatoes.lua b/mods/ITEMS/mcl_farming/potatoes.lua index 871d679634..a7f5a7084c 100644 --- a/mods/ITEMS/mcl_farming/potatoes.lua +++ b/mods/ITEMS/mcl_farming/potatoes.lua @@ -118,7 +118,7 @@ minetest.register_craftitem("mcl_farming:potato_item_baked", { minetest.register_craftitem("mcl_farming:potato_item_poison", { description = S("Poisonous Potato"), - _tt_help = minetest.colorize("#FFFF00", S("60% chance of poisoning")), + _tt_help = minetest.colorize(mcl_colors.YELLOW, S("60% chance of poisoning")), _doc_items_longdesc = S("This potato doesn't look too healthy. You can eat it to restore hunger points, but there's a 60% chance it will poison you briefly."), stack_max = 64, inventory_image = "farming_potato_poison.png", diff --git a/mods/ITEMS/mcl_furnaces/init.lua b/mods/ITEMS/mcl_furnaces/init.lua index 63b4bbc7bd..1d1ecc0319 100644 --- a/mods/ITEMS/mcl_furnaces/init.lua +++ b/mods/ITEMS/mcl_furnaces/init.lua @@ -9,12 +9,12 @@ local LIGHT_ACTIVE_FURNACE = 13 local function active_formspec(fuel_percent, item_percent) return "size[9,8.75]".. - "label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. mcl_formspec.get_itemslot_bg(0,7.74,9,1).. - "label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Furnace"))).."]".. + "label[2.75,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Furnace"))).."]".. "list[current_name;src;2.75,0.5;1,1;]".. mcl_formspec.get_itemslot_bg(2.75,0.5,1,1).. "list[current_name;fuel;2.75,2.5;1,1;]".. @@ -38,12 +38,12 @@ local function active_formspec(fuel_percent, item_percent) end local inactive_formspec = "size[9,8.75]".. - "label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,4;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,4.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,4.5,9,3).. "list[current_player;main;0,7.74;9,1;]".. mcl_formspec.get_itemslot_bg(0,7.74,9,1).. - "label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Furnace"))).."]".. + "label[2.75,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Furnace"))).."]".. "list[current_name;src;2.75,0.5;1,1;]".. mcl_formspec.get_itemslot_bg(2.75,0.5,1,1).. "list[current_name;fuel;2.75,2.5;1,1;]".. diff --git a/mods/ITEMS/mcl_furnaces/mod.conf b/mods/ITEMS/mcl_furnaces/mod.conf index fe0b9c2081..99a1ad0bf9 100644 --- a/mods/ITEMS/mcl_furnaces/mod.conf +++ b/mods/ITEMS/mcl_furnaces/mod.conf @@ -1,3 +1,3 @@ name = mcl_furnaces -depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_craftguide, mcl_achievements, mcl_particles +depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_craftguide, mcl_achievements, mcl_particles, mcl_colors optional_depends = doc, screwdriver diff --git a/mods/ITEMS/mcl_hoppers/init.lua b/mods/ITEMS/mcl_hoppers/init.lua index 3ff549e4f5..e9b3f75e0c 100644 --- a/mods/ITEMS/mcl_hoppers/init.lua +++ b/mods/ITEMS/mcl_hoppers/init.lua @@ -4,10 +4,10 @@ local S = minetest.get_translator("mcl_hoppers") local mcl_hoppers_formspec = "size[9,7]".. - "label[2,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Hopper"))).."]".. + "label[2,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Hopper"))).."]".. "list[current_name;main;2,0.5;5,1;]".. mcl_formspec.get_itemslot_bg(2,0.5,5,1).. - "label[0,2;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[0,2;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]".. "list[current_player;main;0,2.5;9,3;9]".. mcl_formspec.get_itemslot_bg(0,2.5,9,3).. "list[current_player;main;0,5.74;9,1;]".. diff --git a/mods/ITEMS/mcl_hoppers/mod.conf b/mods/ITEMS/mcl_hoppers/mod.conf index c89292f6b4..53f514f392 100644 --- a/mods/ITEMS/mcl_hoppers/mod.conf +++ b/mods/ITEMS/mcl_hoppers/mod.conf @@ -1,4 +1,4 @@ name = mcl_hoppers description = It's just a clone of Minecraft hoppers, functions nearly identical to them minus mesecons making them stop and the way they're placed. -depends = mcl_core, mcl_formspec, mcl_sounds, mcl_util +depends = mcl_core, mcl_formspec, mcl_sounds, mcl_util, mcl_colors optional_depends = doc, screwdriver diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index 650e40ac3e..1b79297229 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -2,7 +2,7 @@ local S = minetest.get_translator("mcl_mobitems") minetest.register_craftitem("mcl_mobitems:rotten_flesh", { description = S("Rotten Flesh"), - _tt_help = minetest.colorize("#FFFF00", S("80% chance of food poisoning")), + _tt_help = minetest.colorize(mcl_colors.YELLOW, S("80% chance of food poisoning")), _doc_items_longdesc = S("Yuck! This piece of flesh clearly has seen better days. If you're really desperate, you can eat it to restore a few hunger points, but there's a 80% chance it causes food poisoning, which increases your hunger for a while."), inventory_image = "mcl_mobitems_rotten_flesh.png", wield_image = "mcl_mobitems_rotten_flesh.png", @@ -63,7 +63,7 @@ minetest.register_craftitem("mcl_mobitems:cooked_beef", { minetest.register_craftitem("mcl_mobitems:chicken", { description = S("Raw Chicken"), - _tt_help = minetest.colorize("#FFFF00", S("30% chance of food poisoning")), + _tt_help = minetest.colorize(mcl_colors.YELLOW, S("30% chance of food poisoning")), _doc_items_longdesc = S("Raw chicken is a food item which is not safe to consume. You can eat it to restore a few hunger points, but there's a 30% chance to suffer from food poisoning, which increases your hunger rate for a while. Cooking raw chicken will make it safe to eat and increases its nutritional value."), inventory_image = "mcl_mobitems_chicken_raw.png", wield_image = "mcl_mobitems_chicken_raw.png", @@ -147,7 +147,7 @@ end minetest.register_craftitem("mcl_mobitems:milk_bucket", { description = S("Milk"), - _tt_help = minetest.colorize("#00FF00", S("Removes all status effects")), + _tt_help = minetest.colorize(mcl_colors.GREEN, S("Removes all status effects")), _doc_items_longdesc = S("Milk is very refreshing and can be obtained by using a bucket on a cow. Drinking it will remove all status effects, but restores no hunger points."), _doc_items_usagehelp = S("Use the placement key to drink the milk."), inventory_image = "mcl_mobitems_bucket_milk.png", @@ -160,7 +160,7 @@ minetest.register_craftitem("mcl_mobitems:milk_bucket", { minetest.register_craftitem("mcl_mobitems:spider_eye", { description = S("Spider Eye"), - _tt_help = minetest.colorize("#FFFF00", S("Poisonous")), + _tt_help = minetest.colorize(mcl_colors.YELLOW, S("Poisonous")), _doc_items_longdesc = S("Spider eyes are used mainly in crafting. If you're really desperate, you can eat a spider eye, but it will poison you briefly."), inventory_image = "mcl_mobitems_spider_eye.png", wield_image = "mcl_mobitems_spider_eye.png", diff --git a/mods/ITEMS/mcl_mobitems/mod.conf b/mods/ITEMS/mcl_mobitems/mod.conf index dc85b6b015..e9604036e6 100644 --- a/mods/ITEMS/mcl_mobitems/mod.conf +++ b/mods/ITEMS/mcl_mobitems/mod.conf @@ -1,2 +1,2 @@ name = mcl_mobitems -depends = mcl_core, mcl_hunger +depends = mcl_core, mcl_hunger, mcl_colors diff --git a/mods/ITEMS/mcl_nether/init.lua b/mods/ITEMS/mcl_nether/init.lua index 30fc171489..4670547675 100644 --- a/mods/ITEMS/mcl_nether/init.lua +++ b/mods/ITEMS/mcl_nether/init.lua @@ -95,7 +95,7 @@ minetest.register_node("mcl_nether:netherrack", { minetest.register_node("mcl_nether:magma", { description = S("Magma Block"), - _tt_help = minetest.colorize("#FFFF00", S("Burns your feet")), + _tt_help = minetest.colorize(mcl_colors.YELLOW, S("Burns your feet")), _doc_items_longdesc = S("Magma blocks are hot solid blocks which hurt anyone standing on it, unless they have fire resistance. Starting a fire on this block will create an eternal fire."), stack_max = 64, tiles = {{name="mcl_nether_magma.png", animation={type="vertical_frames", aspect_w=32, aspect_h=32, length=1.5}}}, diff --git a/mods/ITEMS/mcl_nether/mod.conf b/mods/ITEMS/mcl_nether/mod.conf index 807bf311ee..8bef6c6c97 100644 --- a/mods/ITEMS/mcl_nether/mod.conf +++ b/mods/ITEMS/mcl_nether/mod.conf @@ -1,3 +1,3 @@ name = mcl_nether -depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items +depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items, mcl_colors optional_depends = mcl_death_messages, doc, screwdriver From 600e8bede231906cecf7dbb00e7675df465b2a67 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:35:29 +0200 Subject: [PATCH 070/234] improve wieldview API (!) to support transform registration without groups this will make detaching screwdriver from mcl more easy --- mods/ITEMS/screwdriver/init.lua | 14 +++++++++----- mods/ITEMS/screwdriver/mod.conf | 3 ++- mods/PLAYER/wieldview/transform.lua | 12 +++++------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/mods/ITEMS/screwdriver/init.lua b/mods/ITEMS/screwdriver/init.lua index e6aedf19c5..364032a15e 100644 --- a/mods/ITEMS/screwdriver/init.lua +++ b/mods/ITEMS/screwdriver/init.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator("screwdriver") +local has_wieldview = minetest.get_modpath("wieldview") + screwdriver = {} screwdriver.ROTATE_FACE = 1 @@ -176,7 +178,7 @@ minetest.register_tool("screwdriver:screwdriver", { description = S("Screwdriver"), inventory_image = "screwdriver.png", wield_image = "screwdriver.png^[transformFX", - groups = { tool = 1, not_in_creative_inventory = 1 }, + groups = { tool = 1 }, --not in creative inventory? on_use = function(itemstack, user, pointed_thing) screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 200) return itemstack @@ -197,7 +199,9 @@ minetest.register_craft({ } }) -minetest.register_alias("screwdriver:screwdriver1", "screwdriver:screwdriver") -minetest.register_alias("screwdriver:screwdriver2", "screwdriver:screwdriver") -minetest.register_alias("screwdriver:screwdriver3", "screwdriver:screwdriver") -minetest.register_alias("screwdriver:screwdriver4", "screwdriver:screwdriver") +for i = 1, 4 do + minetest.register_alias("screwdriver:screwdriver"..tostring(i), "screwdriver:screwdriver") + if has_wieldview then + wieldview.register_transform("screwdriver:screwdriver"..tostring(i), "R90") + end +end \ No newline at end of file diff --git a/mods/ITEMS/screwdriver/mod.conf b/mods/ITEMS/screwdriver/mod.conf index a18279839d..5d7800c713 100644 --- a/mods/ITEMS/screwdriver/mod.conf +++ b/mods/ITEMS/screwdriver/mod.conf @@ -1,2 +1,3 @@ name = screwdriver -depends = mcl_wip \ No newline at end of file +depends = mcl_wip +optional_depends = wieldview \ No newline at end of file diff --git a/mods/PLAYER/wieldview/transform.lua b/mods/PLAYER/wieldview/transform.lua index a19956796f..b55621d7ee 100644 --- a/mods/PLAYER/wieldview/transform.lua +++ b/mods/PLAYER/wieldview/transform.lua @@ -1,10 +1,8 @@ -- Wielded Item Transformations - http://dev.minetest.net/texture -wieldview.transform = { - ["screwdriver:screwdriver"]="R90", - ["screwdriver:screwdriver1"]="R90", - ["screwdriver:screwdriver2"]="R90", - ["screwdriver:screwdriver3"]="R90", - ["screwdriver:screwdriver4"]="R90", -} +wieldview.register_transform = function(item, rotation) + wieldview.transform[item] = rotation +end + +wieldview.transform = {} From 3a514ecdadb1fd697eb586746c39b0a7a5db949e Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:44:38 +0200 Subject: [PATCH 071/234] remove duplicated code --- mods/ENTITIES/mcl_boats/init.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index 29d5c2256a..efb6c073e3 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -12,9 +12,7 @@ local function is_group(pos, group) return minetest.get_item_group(nn, group) ~= 0 end -local function is_water(pos) - return is_group(pos, "water") -end +local is_water = flowlib.is_water local function is_ice(pos) return is_group(pos, "ice") From f60941003d21230ce9cb8b4b3ccfe19895c685fe Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:49:05 +0200 Subject: [PATCH 072/234] fix the stupidiest typo ever :-/ --- mods/ENTITIES/mcl_falling_nodes/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_falling_nodes/init.lua b/mods/ENTITIES/mcl_falling_nodes/init.lua index 5b94373d95..7656c15d55 100644 --- a/mods/ENTITIES/mcl_falling_nodes/init.lua +++ b/mods/ENTITIES/mcl_falling_nodes/init.lua @@ -2,7 +2,7 @@ local S = minetest.get_translator("mcl_falling_nodes") local dmes = minetest.get_modpath("mcl_death_messages") ~= nil local has_mcl_armor = minetest.get_modpath("mcl_armor") -local his_creative_enabled = minetest.is_creative_enabled +local is_creative_enabled = minetest.is_creative_enabled local get_falling_depth = function(self) if not self._startpos then From c70ea7c843a587edda6e3e0b267789862d64953b Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:49:54 +0200 Subject: [PATCH 073/234] fix crash :-/ I am stupid --- mods/ENTITIES/mcl_falling_nodes/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_falling_nodes/init.lua b/mods/ENTITIES/mcl_falling_nodes/init.lua index 7656c15d55..6e69f89112 100644 --- a/mods/ENTITIES/mcl_falling_nodes/init.lua +++ b/mods/ENTITIES/mcl_falling_nodes/init.lua @@ -53,7 +53,7 @@ local deal_falling_damage = function(self, dtime) local helmet = inv:get_stack("armor", 2) if has_mcl_armor and not helmet:is_empty() then hp = hp/4*3 - if not his_creative_enabled(name) then + if not is_creative_enabled(name) then helmet:add_wear(65535/helmet:get_definition().groups.mcl_armor_uses) --TODO: be sure damage is exactly like mc (informations are missing in the mc wiki) inv:set_stack("armor", 2, helmet) end From 7ec7012572112f71d4fbcb6bbc7a7db260ef0be5 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:50:58 +0200 Subject: [PATCH 074/234] fix indentation --- mods/ENTITIES/mcl_minecarts/init.lua | 44 +++++++++++++--------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index 9c61fa5edf..d21850d838 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -824,29 +824,27 @@ minetest.register_craft({ -- TODO: Re-enable crafting of special minecarts when they have been implemented if false then + minetest.register_craft({ + output = "mcl_minecarts:furnace_minecart", + recipe = { + {"mcl_furnaces:furnace"}, + {"mcl_minecarts:minecart"}, + }, + }) -minetest.register_craft({ - output = "mcl_minecarts:furnace_minecart", - recipe = { - {"mcl_furnaces:furnace"}, - {"mcl_minecarts:minecart"}, - }, -}) - -minetest.register_craft({ - output = "mcl_minecarts:hopper_minecart", - recipe = { - {"mcl_hoppers:hopper"}, - {"mcl_minecarts:minecart"}, - }, -}) - -minetest.register_craft({ - output = "mcl_minecarts:chest_minecart", - recipe = { - {"mcl_chests:chest"}, - {"mcl_minecarts:minecart"}, - }, -}) + minetest.register_craft({ + output = "mcl_minecarts:hopper_minecart", + recipe = { + {"mcl_hoppers:hopper"}, + {"mcl_minecarts:minecart"}, + }, + }) + minetest.register_craft({ + output = "mcl_minecarts:chest_minecart", + recipe = { + {"mcl_chests:chest"}, + {"mcl_minecarts:minecart"}, + }, + }) end From 369c8b9b8aed6af23f6e41c7861a55345568b9b1 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:54:58 +0200 Subject: [PATCH 075/234] remove hard depend to mcl_wip in mcl_minecarts --- mods/ENTITIES/mcl_minecarts/init.lua | 17 +++++++++-------- mods/ENTITIES/mcl_minecarts/mod.conf | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index d21850d838..70bf164772 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator("mcl_minecarts") +local has_mcl_wip = minetest.get_modpath("mcl_wip") + mcl_minecarts = {} mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts") mcl_minecarts.speed_max = 10 @@ -662,8 +664,6 @@ register_minecart( "mcl_minecarts_minecart_chest.png", {"mcl_minecarts:minecart", "mcl_chests:chest"}, nil, nil, false) - -mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") -- Minecart with Furnace register_minecart( @@ -719,8 +719,6 @@ register_minecart( end, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") - -- Minecart with Command Block register_minecart( "mcl_minecarts:command_block_minecart", @@ -742,8 +740,6 @@ register_minecart( nil, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") - -- Minecart with Hopper register_minecart( "mcl_minecarts:hopper_minecart", @@ -762,8 +758,6 @@ register_minecart( nil, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") - -- Minecart with TNT register_minecart( "mcl_minecarts:tnt_minecart", @@ -848,3 +842,10 @@ if false then }, }) end + +if has_mcl_wip then + mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") + mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") + mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") + mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") +end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 138fd18e6c..9fff9175df 100644 --- a/mods/ENTITIES/mcl_minecarts/mod.conf +++ b/mods/ENTITIES/mcl_minecarts/mod.conf @@ -1,6 +1,6 @@ name = mcl_minecarts author = Krock description = Minecarts are vehicles to move players quickly on rails. -depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_wip -optional_depends = doc_identifier +depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons +optional_depends = doc_identifier, mcl_wip From 7a5c2d617b2af0993965bc1b0be11e3e37b6489d Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:57:46 +0200 Subject: [PATCH 076/234] Revert "remove hard depend to mcl_wip in mcl_minecarts" This reverts commit 369c8b9b8aed6af23f6e41c7861a55345568b9b1. --- mods/ENTITIES/mcl_minecarts/init.lua | 17 ++++++++--------- mods/ENTITIES/mcl_minecarts/mod.conf | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index 70bf164772..d21850d838 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -1,7 +1,5 @@ local S = minetest.get_translator("mcl_minecarts") -local has_mcl_wip = minetest.get_modpath("mcl_wip") - mcl_minecarts = {} mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts") mcl_minecarts.speed_max = 10 @@ -664,6 +662,8 @@ register_minecart( "mcl_minecarts_minecart_chest.png", {"mcl_minecarts:minecart", "mcl_chests:chest"}, nil, nil, false) + +mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") -- Minecart with Furnace register_minecart( @@ -719,6 +719,8 @@ register_minecart( end, nil, false ) +mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") + -- Minecart with Command Block register_minecart( "mcl_minecarts:command_block_minecart", @@ -740,6 +742,8 @@ register_minecart( nil, nil, false ) +mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") + -- Minecart with Hopper register_minecart( "mcl_minecarts:hopper_minecart", @@ -758,6 +762,8 @@ register_minecart( nil, nil, false ) +mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") + -- Minecart with TNT register_minecart( "mcl_minecarts:tnt_minecart", @@ -842,10 +848,3 @@ if false then }, }) end - -if has_mcl_wip then - mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") - mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") - mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") - mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 9fff9175df..138fd18e6c 100644 --- a/mods/ENTITIES/mcl_minecarts/mod.conf +++ b/mods/ENTITIES/mcl_minecarts/mod.conf @@ -1,6 +1,6 @@ name = mcl_minecarts author = Krock description = Minecarts are vehicles to move players quickly on rails. -depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons -optional_depends = doc_identifier, mcl_wip +depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_wip +optional_depends = doc_identifier From 41a8cd0e15463ba975580beecc7a7097ba675437 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:58:02 +0200 Subject: [PATCH 077/234] Revert "Revert "remove hard depend to mcl_wip in mcl_minecarts"" This reverts commit 7a5c2d617b2af0993965bc1b0be11e3e37b6489d. --- mods/ENTITIES/mcl_minecarts/init.lua | 17 +++++++++-------- mods/ENTITIES/mcl_minecarts/mod.conf | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index d21850d838..70bf164772 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator("mcl_minecarts") +local has_mcl_wip = minetest.get_modpath("mcl_wip") + mcl_minecarts = {} mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts") mcl_minecarts.speed_max = 10 @@ -662,8 +664,6 @@ register_minecart( "mcl_minecarts_minecart_chest.png", {"mcl_minecarts:minecart", "mcl_chests:chest"}, nil, nil, false) - -mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") -- Minecart with Furnace register_minecart( @@ -719,8 +719,6 @@ register_minecart( end, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") - -- Minecart with Command Block register_minecart( "mcl_minecarts:command_block_minecart", @@ -742,8 +740,6 @@ register_minecart( nil, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") - -- Minecart with Hopper register_minecart( "mcl_minecarts:hopper_minecart", @@ -762,8 +758,6 @@ register_minecart( nil, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") - -- Minecart with TNT register_minecart( "mcl_minecarts:tnt_minecart", @@ -848,3 +842,10 @@ if false then }, }) end + +if has_mcl_wip then + mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") + mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") + mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") + mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") +end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 138fd18e6c..9fff9175df 100644 --- a/mods/ENTITIES/mcl_minecarts/mod.conf +++ b/mods/ENTITIES/mcl_minecarts/mod.conf @@ -1,6 +1,6 @@ name = mcl_minecarts author = Krock description = Minecarts are vehicles to move players quickly on rails. -depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_wip -optional_depends = doc_identifier +depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons +optional_depends = doc_identifier, mcl_wip From 857a0c55658a316c7adf64815218c36fe6da12e4 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:58:36 +0200 Subject: [PATCH 078/234] Revert "remove hard depend to mcl_wip in mcl_minecarts" This reverts commit 369c8b9b8aed6af23f6e41c7861a55345568b9b1. --- mods/ENTITIES/mcl_minecarts/init.lua | 17 ++++++++--------- mods/ENTITIES/mcl_minecarts/mod.conf | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index 70bf164772..d21850d838 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -1,7 +1,5 @@ local S = minetest.get_translator("mcl_minecarts") -local has_mcl_wip = minetest.get_modpath("mcl_wip") - mcl_minecarts = {} mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts") mcl_minecarts.speed_max = 10 @@ -664,6 +662,8 @@ register_minecart( "mcl_minecarts_minecart_chest.png", {"mcl_minecarts:minecart", "mcl_chests:chest"}, nil, nil, false) + +mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") -- Minecart with Furnace register_minecart( @@ -719,6 +719,8 @@ register_minecart( end, nil, false ) +mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") + -- Minecart with Command Block register_minecart( "mcl_minecarts:command_block_minecart", @@ -740,6 +742,8 @@ register_minecart( nil, nil, false ) +mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") + -- Minecart with Hopper register_minecart( "mcl_minecarts:hopper_minecart", @@ -758,6 +762,8 @@ register_minecart( nil, nil, false ) +mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") + -- Minecart with TNT register_minecart( "mcl_minecarts:tnt_minecart", @@ -842,10 +848,3 @@ if false then }, }) end - -if has_mcl_wip then - mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") - mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") - mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") - mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 9fff9175df..138fd18e6c 100644 --- a/mods/ENTITIES/mcl_minecarts/mod.conf +++ b/mods/ENTITIES/mcl_minecarts/mod.conf @@ -1,6 +1,6 @@ name = mcl_minecarts author = Krock description = Minecarts are vehicles to move players quickly on rails. -depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons -optional_depends = doc_identifier, mcl_wip +depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_wip +optional_depends = doc_identifier From 59c13b6df81e59c57ef805578bc087c3b1da8c44 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:58:45 +0200 Subject: [PATCH 079/234] Revert "Revert "remove hard depend to mcl_wip in mcl_minecarts"" This reverts commit 857a0c55658a316c7adf64815218c36fe6da12e4. --- mods/ENTITIES/mcl_minecarts/init.lua | 17 +++++++++-------- mods/ENTITIES/mcl_minecarts/mod.conf | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index d21850d838..70bf164772 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator("mcl_minecarts") +local has_mcl_wip = minetest.get_modpath("mcl_wip") + mcl_minecarts = {} mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts") mcl_minecarts.speed_max = 10 @@ -662,8 +664,6 @@ register_minecart( "mcl_minecarts_minecart_chest.png", {"mcl_minecarts:minecart", "mcl_chests:chest"}, nil, nil, false) - -mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") -- Minecart with Furnace register_minecart( @@ -719,8 +719,6 @@ register_minecart( end, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") - -- Minecart with Command Block register_minecart( "mcl_minecarts:command_block_minecart", @@ -742,8 +740,6 @@ register_minecart( nil, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") - -- Minecart with Hopper register_minecart( "mcl_minecarts:hopper_minecart", @@ -762,8 +758,6 @@ register_minecart( nil, nil, false ) -mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") - -- Minecart with TNT register_minecart( "mcl_minecarts:tnt_minecart", @@ -848,3 +842,10 @@ if false then }, }) end + +if has_mcl_wip then + mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") + mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") + mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") + mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") +end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 138fd18e6c..9fff9175df 100644 --- a/mods/ENTITIES/mcl_minecarts/mod.conf +++ b/mods/ENTITIES/mcl_minecarts/mod.conf @@ -1,6 +1,6 @@ name = mcl_minecarts author = Krock description = Minecarts are vehicles to move players quickly on rails. -depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_wip -optional_depends = doc_identifier +depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons +optional_depends = doc_identifier, mcl_wip From 613779a851049feb4fa8bc067490cdba45c12962 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:59:00 +0200 Subject: [PATCH 080/234] Revert "improve wieldview API (!)" This reverts commit 600e8bede231906cecf7dbb00e7675df465b2a67. --- mods/ITEMS/screwdriver/init.lua | 14 +++++--------- mods/ITEMS/screwdriver/mod.conf | 3 +-- mods/PLAYER/wieldview/transform.lua | 12 +++++++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/mods/ITEMS/screwdriver/init.lua b/mods/ITEMS/screwdriver/init.lua index 364032a15e..e6aedf19c5 100644 --- a/mods/ITEMS/screwdriver/init.lua +++ b/mods/ITEMS/screwdriver/init.lua @@ -1,7 +1,5 @@ local S = minetest.get_translator("screwdriver") -local has_wieldview = minetest.get_modpath("wieldview") - screwdriver = {} screwdriver.ROTATE_FACE = 1 @@ -178,7 +176,7 @@ minetest.register_tool("screwdriver:screwdriver", { description = S("Screwdriver"), inventory_image = "screwdriver.png", wield_image = "screwdriver.png^[transformFX", - groups = { tool = 1 }, --not in creative inventory? + groups = { tool = 1, not_in_creative_inventory = 1 }, on_use = function(itemstack, user, pointed_thing) screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 200) return itemstack @@ -199,9 +197,7 @@ minetest.register_craft({ } }) -for i = 1, 4 do - minetest.register_alias("screwdriver:screwdriver"..tostring(i), "screwdriver:screwdriver") - if has_wieldview then - wieldview.register_transform("screwdriver:screwdriver"..tostring(i), "R90") - end -end \ No newline at end of file +minetest.register_alias("screwdriver:screwdriver1", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver2", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver3", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver4", "screwdriver:screwdriver") diff --git a/mods/ITEMS/screwdriver/mod.conf b/mods/ITEMS/screwdriver/mod.conf index 5d7800c713..a18279839d 100644 --- a/mods/ITEMS/screwdriver/mod.conf +++ b/mods/ITEMS/screwdriver/mod.conf @@ -1,3 +1,2 @@ name = screwdriver -depends = mcl_wip -optional_depends = wieldview \ No newline at end of file +depends = mcl_wip \ No newline at end of file diff --git a/mods/PLAYER/wieldview/transform.lua b/mods/PLAYER/wieldview/transform.lua index b55621d7ee..a19956796f 100644 --- a/mods/PLAYER/wieldview/transform.lua +++ b/mods/PLAYER/wieldview/transform.lua @@ -1,8 +1,10 @@ -- Wielded Item Transformations - http://dev.minetest.net/texture -wieldview.register_transform = function(item, rotation) - wieldview.transform[item] = rotation -end - -wieldview.transform = {} +wieldview.transform = { + ["screwdriver:screwdriver"]="R90", + ["screwdriver:screwdriver1"]="R90", + ["screwdriver:screwdriver2"]="R90", + ["screwdriver:screwdriver3"]="R90", + ["screwdriver:screwdriver4"]="R90", +} From c35dab1d0876f0c213538d3d9f4c3b7510edf8c7 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 00:59:52 +0200 Subject: [PATCH 081/234] try to fix crash --- mods/ENTITIES/mcl_boats/mod.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_boats/mod.conf b/mods/ENTITIES/mcl_boats/mod.conf index 251459186a..a5d6cc8cb4 100644 --- a/mods/ENTITIES/mcl_boats/mod.conf +++ b/mods/ENTITIES/mcl_boats/mod.conf @@ -1,7 +1,7 @@ name = mcl_boats author = PilzAdam description = Adds drivable boats. -depends = mcl_player +depends = mcl_player, flowlib optional_depends = mcl_core, doc_identifier From d4e0d4d1c107d4c0ce6b6093ccac7cfe44c169ae Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 01:00:17 +0200 Subject: [PATCH 082/234] Revert "Revert "improve wieldview API (!)"" This reverts commit 613779a851049feb4fa8bc067490cdba45c12962. --- mods/ITEMS/screwdriver/init.lua | 14 +++++++++----- mods/ITEMS/screwdriver/mod.conf | 3 ++- mods/PLAYER/wieldview/transform.lua | 12 +++++------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/mods/ITEMS/screwdriver/init.lua b/mods/ITEMS/screwdriver/init.lua index e6aedf19c5..364032a15e 100644 --- a/mods/ITEMS/screwdriver/init.lua +++ b/mods/ITEMS/screwdriver/init.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator("screwdriver") +local has_wieldview = minetest.get_modpath("wieldview") + screwdriver = {} screwdriver.ROTATE_FACE = 1 @@ -176,7 +178,7 @@ minetest.register_tool("screwdriver:screwdriver", { description = S("Screwdriver"), inventory_image = "screwdriver.png", wield_image = "screwdriver.png^[transformFX", - groups = { tool = 1, not_in_creative_inventory = 1 }, + groups = { tool = 1 }, --not in creative inventory? on_use = function(itemstack, user, pointed_thing) screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 200) return itemstack @@ -197,7 +199,9 @@ minetest.register_craft({ } }) -minetest.register_alias("screwdriver:screwdriver1", "screwdriver:screwdriver") -minetest.register_alias("screwdriver:screwdriver2", "screwdriver:screwdriver") -minetest.register_alias("screwdriver:screwdriver3", "screwdriver:screwdriver") -minetest.register_alias("screwdriver:screwdriver4", "screwdriver:screwdriver") +for i = 1, 4 do + minetest.register_alias("screwdriver:screwdriver"..tostring(i), "screwdriver:screwdriver") + if has_wieldview then + wieldview.register_transform("screwdriver:screwdriver"..tostring(i), "R90") + end +end \ No newline at end of file diff --git a/mods/ITEMS/screwdriver/mod.conf b/mods/ITEMS/screwdriver/mod.conf index a18279839d..5d7800c713 100644 --- a/mods/ITEMS/screwdriver/mod.conf +++ b/mods/ITEMS/screwdriver/mod.conf @@ -1,2 +1,3 @@ name = screwdriver -depends = mcl_wip \ No newline at end of file +depends = mcl_wip +optional_depends = wieldview \ No newline at end of file diff --git a/mods/PLAYER/wieldview/transform.lua b/mods/PLAYER/wieldview/transform.lua index a19956796f..b55621d7ee 100644 --- a/mods/PLAYER/wieldview/transform.lua +++ b/mods/PLAYER/wieldview/transform.lua @@ -1,10 +1,8 @@ -- Wielded Item Transformations - http://dev.minetest.net/texture -wieldview.transform = { - ["screwdriver:screwdriver"]="R90", - ["screwdriver:screwdriver1"]="R90", - ["screwdriver:screwdriver2"]="R90", - ["screwdriver:screwdriver3"]="R90", - ["screwdriver:screwdriver4"]="R90", -} +wieldview.register_transform = function(item, rotation) + wieldview.transform[item] = rotation +end + +wieldview.transform = {} From a040355dce5246019531b217c8e203673402ebbc Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 30 Mar 2021 01:00:51 +0200 Subject: [PATCH 083/234] Revert "Revert "Revert "improve wieldview API (!)""" This reverts commit d4e0d4d1c107d4c0ce6b6093ccac7cfe44c169ae. --- mods/ITEMS/screwdriver/init.lua | 14 +++++--------- mods/ITEMS/screwdriver/mod.conf | 3 +-- mods/PLAYER/wieldview/transform.lua | 12 +++++++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/mods/ITEMS/screwdriver/init.lua b/mods/ITEMS/screwdriver/init.lua index 364032a15e..e6aedf19c5 100644 --- a/mods/ITEMS/screwdriver/init.lua +++ b/mods/ITEMS/screwdriver/init.lua @@ -1,7 +1,5 @@ local S = minetest.get_translator("screwdriver") -local has_wieldview = minetest.get_modpath("wieldview") - screwdriver = {} screwdriver.ROTATE_FACE = 1 @@ -178,7 +176,7 @@ minetest.register_tool("screwdriver:screwdriver", { description = S("Screwdriver"), inventory_image = "screwdriver.png", wield_image = "screwdriver.png^[transformFX", - groups = { tool = 1 }, --not in creative inventory? + groups = { tool = 1, not_in_creative_inventory = 1 }, on_use = function(itemstack, user, pointed_thing) screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 200) return itemstack @@ -199,9 +197,7 @@ minetest.register_craft({ } }) -for i = 1, 4 do - minetest.register_alias("screwdriver:screwdriver"..tostring(i), "screwdriver:screwdriver") - if has_wieldview then - wieldview.register_transform("screwdriver:screwdriver"..tostring(i), "R90") - end -end \ No newline at end of file +minetest.register_alias("screwdriver:screwdriver1", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver2", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver3", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver4", "screwdriver:screwdriver") diff --git a/mods/ITEMS/screwdriver/mod.conf b/mods/ITEMS/screwdriver/mod.conf index 5d7800c713..a18279839d 100644 --- a/mods/ITEMS/screwdriver/mod.conf +++ b/mods/ITEMS/screwdriver/mod.conf @@ -1,3 +1,2 @@ name = screwdriver -depends = mcl_wip -optional_depends = wieldview \ No newline at end of file +depends = mcl_wip \ No newline at end of file diff --git a/mods/PLAYER/wieldview/transform.lua b/mods/PLAYER/wieldview/transform.lua index b55621d7ee..a19956796f 100644 --- a/mods/PLAYER/wieldview/transform.lua +++ b/mods/PLAYER/wieldview/transform.lua @@ -1,8 +1,10 @@ -- Wielded Item Transformations - http://dev.minetest.net/texture -wieldview.register_transform = function(item, rotation) - wieldview.transform[item] = rotation -end - -wieldview.transform = {} +wieldview.transform = { + ["screwdriver:screwdriver"]="R90", + ["screwdriver:screwdriver1"]="R90", + ["screwdriver:screwdriver2"]="R90", + ["screwdriver:screwdriver3"]="R90", + ["screwdriver:screwdriver4"]="R90", +} From a14959ac706db635e59733f2b44fe2999385a0b6 Mon Sep 17 00:00:00 2001 From: epCode Date: Tue, 30 Mar 2021 09:53:55 -0700 Subject: [PATCH 084/234] add player death animation and particles --- mods/ITEMS/mcl_armor/armor.lua | 1 + .../mcl_armor/models/mcl_armor_character.b3d | Bin 335992 -> 343384 bytes .../models/mcl_armor_character.blend | Bin 1099020 -> 1187156 bytes mods/PLAYER/mcl_player/init.lua | 27 +++++++++++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index a879f72403..05a0200167 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -367,6 +367,7 @@ mcl_player.player_register_model("mcl_armor_character.b3d", { run_walk = {x=440, y=459}, run_walk_mine = {x=461, y=480}, sit_mount = {x=484, y=484}, + die = {x=498, y=498}, }, }) diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d b/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d index c6a1274c5554bb3438b068638c5be98fb4ba4438..a658f753c3b423573cd735f196876364467c87c2 100644 GIT binary patch delta 58161 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 delta 52591 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%0Avr35nMc=Ni^_989E>nIXG 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ⅅPIgBHhVCj+z3HOkfJ zsMrb<&$Uzj`c3r)zjZ4fHexl07N*#Iw!J)h1_&_?Cmmq)rG}Z?Vs12(wHf@v4owL_ zVv4(yaA^8l8>aDFJ@d_8rac{Uq_uXZ!^|0dk6BMt0`JT9&(*ou7Whono-0UtlNTa6 zv=I|O9}l44bAMXK{V?%M`?- zC%6v+ZNw^9ox>`FZlga9W8GhH2lLHp(*EzjDSU0%D_45cx`)T}z5hG#8Tw7h;yi1p zyJ4O>m;0U#hTXBh6%zpbYZF~F9sTwvjr^8t`x)nOIDI5AEk64^l&XU6oay7o<=0UH z^!`ED$RjW#a9Rb`XNUC_PAlzu&u8e@sd|9Yz8$mN+yY2yNf}DkR#?zd z;}(X8-8@d$Y&-e`4;l8PH$0)@`&A74tCM!!X@6@x>`$L=x4-7*$nE1{WPk7`*cZpJ zKhWD*_SY=+pd$U?YJ2cyyLe!KkYB9!2fK;I{_3bmj3?^pn(acLD*f|O>KvlO>}+Yx zGwk-)T2vHbJ7-+AUll%~>U9ViANx&67OPloP}8!q!{oEF=sCzt!#+{o&a%%s-#)`C zNWeZJzgX;Z9hFokcE$E-wJq44exb5IeW1iwtXJ)3t;DM&E|a)f+SMXS=Lp`rlDc!I+qQm$$`5$7-*q$X{zE8j z`hC8Ka0EBrOjrW^0(5qkUljX(0g+Q|ZPTpR77&YmxT%BuV(|-xhrO8Xw%Cz=j@aQQ zWq+_cJnuCUuEjiri`b$_ct^6`@lOKE#q(to-H(J1JhwO!UOz6AI}8aZ7tgaB>3$@9 z;JL+-@Q&hgF;J&V_!*vq;b-x_Z|rVx>pebCll?1h{O)`AtiENvZYv4a&uqF4`LUnz zJT3>C!=Ue#7~d_K@T2kj^PH|$bMuM`AD+3+xTd5$2WT3tht9}?72$DwV^ywR+b20D)rVMQCTG!ysrLz!LQ{&U0kJ^OKN*eLih z$QpE$k~mLb8W@N30LSHU^HnGF8_&=+c!d38ZVmQ}e5Mn=248Js;X9Y%xvtK&6KVdK zL5W7>qwIm@X#H70llV0m)6S5wgp6&u z+zMLoi@hT!krA*R^p?FObQx0^GGy@J@c+DE)uQThe%F)*8s#Z9M<;Tqfp85WCG`D3ZLUKRip|QjC^1@Jrj; za5osf7mbeI)a7XY)?~C0jZVwPc<4l!qumr69Xr3)XMXFo9g0(|ALIF7sr`8VvHVfeQ8q{%!8*BJ6pbx$XFtk=JfCYjuHFEKe;9d#cS;AKyhEqnW+@k*1ey0XjWjYf=3Ma zcw;?vgt4E6ZOE9%l=`g}Ic||O=)SDIV*75Qb6uI&cjiDJ^gustjFJ!J_pnpDAoz)M-7WBW9+Q3D_#}Mll)Ti6_I*M| z|E=;f#3%=C4BK^xZX!PtUmd#M{2|3xv&3F}A>WHHuE%a!KP~N7l}CF$wWKUKE13A` zhud0for@@q_j`~P$NIoWjrAd{$1F;t-M-g@ueSTaXw@tQwDX8z$DoV*UUZwUQs)2~ z#Ed`gZ;GvSQ%QN?XA)h*Cc`wmuO`o&M*IJQm9!PGl)se5-=T~%@arPiaJB2**lxDS zm;tdDRw`vc7G5xJ_gNo2_5uBg9&&>|rt)__$rfNIcX`-_TUmT>>MX;OtCy7qy+C5R z@21;pV#16B#N()}ETNs5oThAu(`u}u_7#~FvieOjSGLPdhE@1X%RLBv_sl))?z+3x zz6iu@PsLORq<`*VAF~P;SG4ErKWh9L%9JrAm6)2%qMM#WV^Ye*IBYfDi$~tmbFwSx zGqiNDu9omOOPLS1GOwlkf!Ex}wJ#iNKNn9=`sa2&f6gnY@3MR4?)v+6U#wR9Tk4$c zHp?QsD~09q4gGApLUuj7wi2^!saO+u=5qSE*L^EpHymp|Ut3|U*UmiPIbkBf#RCia zh#9v-@Iyk8WBM61`5GZ)xkuMVpx7wCaomRWk6hUQ*tLAOSYmvC?(A2G1B zRVPvVKrKV>Y=)sG3871pT0N5T3f)Q4=*SF;v$U=R;;bjqh(V%#v3_<Y@LOW<3lUlhAw;0yDiC?!!yNei<&`yId7U|{ zrhoQcYV<4cTQ5f0KfUr|zR&*2jRJ+hP0Bw}t}cA2+(iDucD6LNw!YF-cfdK+=ez5T z&YUuQ`QrEfHVoHJp9tjjUi)D3!NZfpZ|R!G2%$_Bb2UPZe9dr*+t5h8_x2I%7px!2 za87(DJkusPra>`>EzI)>x-jsKTf6lSVX{(SHJr%$!gd7r~Zb! zf8K7bRwuY-|1{ns3{~$HPDB4$eVXB)tB6N-oz(`fVLk9Y-MAO|57Xy|DP8DIA;eXL z((-2d=ndD+q7%1wWHE&=-yJcg_37F5Ev=sz>A8>peN2}=JL+pCJ#I?&*r8{fwPE)6 zDu2;i$%W%)Tz7iI zQ}3yC*1}(mo6!B@hSdL4>HThBKki50-O@1kFDm`~fOp5eRr802`gJOO$CUjtwhw-~ zq06sS`jK0Y$#{3kYYl1FtMvQ>MrJ(s@Q#K+txC^s3}jp|EUEE^LY1z6^M@J3Zqpl6 z&s6DN&n?X8Q{1a@TeeCsZT(Tk)|>h?-Y`m~o6>7Dp6dOB#x+A!`iSg{GM;(s2aR(F zskFYXHsdwQ|CQt)*{3>V?9E~P@|mR>|FqCQZ)HJ7#R|Q#pOpWX6J}?mj!0^}R`@HL zmzRP7w;eXmWR{oH=sdE*Y*`r(FV z(ci|ePaLOz9@g*gul{!I_Bmnw-}<`;$6kD7*gg(9`uwq<{WWYqpPcyjF}b&d?Th>B zZq!b~-p(2H_b0|%@;^D|{3pM);IDk(!6&WsU%KYoCqJ~5zxbOI*Y9uPui*Ie)*ou& zfAP&%uea9k+VcC?TkGHJjOW)|<&*W3PuG89k>9_r>rsENMZVAc=a~ANE%IOcr(yM} z7XAF+yuA8J7X1a%X4m((==Y741@)B{{eL;LwBBkT_w}i+&#>6fFV@x8TkY$Vt+sGH>Hb(VN!)d#2uy^|s`nyL$cVA3wZd z^hYY)FX@W)gX<@4sQ*l*FaJES{`k4K)zAJ)rN2JE&-xpd_8eCy?aiVgo1PpoYfi?x z?^OO9znc5x`jYaDfzn&ce`d(v~E>n zgnQd}`#tq-9bnBo^W7E!>ldi(qr0qicd}H?FTBUzU?cu5;cGPeCPNk2g_Hg*~v+GxgJ#l;ZKk9G4lC;zQ z=2Lsv<@#{`m((7PwBX-K?cp63`ma%Y7_yXKPVM1K7XAvUJ+$&)M(v@se%DibXs!Q& z)E;)X$S0H9L#zB=q4v-!-#=4(XqErN)E-*(^D4E6R{c$;_Ry+dZV#>c|AN{>t9|^M z+C!`TaC>OAFK!R5_Q&nvQTv7MkK4m`{)r8mv=7`KUVrh-4IybixINr4 z{QmlMXYdtRmd^T=O=XF>ga}qRn}moV$}pVBY6@dOyVUCgt_!xf$*EG7pq{ zcQVaoaM;o`;DPpGwZd~yAEBYGNj+r{%XFS*a#+_9_0 z8KpeaKgAzS|LiCJDSqokhW&FYudi2sy}%;hxAuXl@o3V+eHv3cOL)StF3Crn{iUAgfP`#o!YaGgS9gk3$p zt()rZpLgvlF~(Sq>7U|{rhooQ{8RkaiyW=OQ{&tG870+)#fdE;u=uBb&u;b4#-z}Q zQ^*g}x@e)_sXE(juQ|8(+I5!kZIAEz82&`}C|2(!`5waw{>V|?dA?ospL~DG#%~@8 z`)??d;D^(Fg3+`-La%n?H---wu}4E z?e62-yOq*9&0o_$#UD-oTqFJ|e(S}s>7QB$J%6qe|BO^0`K>qn>@lW_W!HBfmB6eW({uwENcnvqF8JU5`?3G?L-`w)V93>gAdEh2i+BEv)n2 z(@DM8)-?7R{%@ke7=L-9&m-IDn(i6?MAwafrF#s=`J?g|)N8#~jn$g|IF4xz>9ckC zQVagG1p5ZzR|`H}H~w$XW5Y)f9OF;h{J*B3|7&ojvSBy=7;0ArHy&cYXRQxkzdrMd ztOWftN~M`6>(36Z2i(WEYJH3yc6X*s{}g{T{d1f6r}(WGj{#agEEBjL-d=ZPGgP#7U|{rhmRI{waRz#U77udH&Y% z_&GSPDI-h&S@*zhef~81M0;KBJ{$l0Pi>TQ{`Mlr^Cz!?CA!A*=VS7IO{!h7bGPeLc6q4s>oDvuV8;!0@K7?&mBY$`!KnkECB&+u`6tPX7tt|Lx`{GcP;;Pmi4c_8P~y)eXl^-QI87;eWE`vI%{@Sjx1GIh+fQ zdVRz8L*L4{W#MH;ITx2K$sFJ3(uM_7-Zs8lZm$FQi&P%+?B%Mv>K!V*pP_dyn)I<6 z@nPII_@S-6{5gZ)gx}$4BMJ6IO0QwKD~SK|iRX)mPof#>O?7D@{xgVYF5~;wKM%i| z>Qboq4=uTET2s!5BQ~DWKWP)=fAT8NjlDYjsweg{>ZjfO^0=XgUz|B;`eXzDz{9$4 z=vz8@!j{i3GUV~M^lKWgx%}>|shRg~RD4n)(h$?9Pr1mHm+24o&C^MQbkj>t4Bl}; zpLek9b7;qv(77m?{gl*uPw1z}mOC)4%3@+>KPBhXt)_d1C30pAVS3Jt(t>65&E_DT z@Y0UpR_66YFL0#&d%`GU+vV}~Q*QJ@E0GxI;Ut1<#nDsM_g<~{IJ48tMh-G0ZzlSx--g08^}-{TNcWf}MA+6WYfGCzKG zd1Ln{xsR$f`pIu@etG?H>Z68HU&T;64(&dk`=~>xuj2G8>DOdF+;m6wpPKTs8QL6L)OAr$^(6rx8_n+zhWu3 zL-u}H$^(6rr%O5DqeIrRTgn4{lxOz!Qcq)TF2T1qz&=4A<$*5v=#aG%M3l=j=8~k% z-xJ2@d^SbL1vN%zIcy=K7`v6wHMc``jxikfya&@yg(QvqNS(ZhTkVXUC&oq|?WliJzMu#>SnHca5PAh@a1EDP#-@?! zljf5i)Lh|#Pj9LpPd~!zyj!dk1k7qrjW?P;H_vQXE~_RX1QDC<4zwKGpqOh@}HbzoXfdhRs6 z;W`9A#HCUQ@lW_S`x9&XtYE_JGtZGNd3saEH2P7VwvFb<<~=jJ@$)l#8Tg;l9NEC( zy)vI&tJ>==G)LCu_Vnyue%3#W>tyjwzkOx_?!sWU&+;vq)l{}cA5l3$`#dZvWMlxh zGH;B4vTaf*u6OO7b^KiS$lf-7=5HT_=&Tj>4TP`?(at&Bs_=b`pWpt=tyy6_zH-B{ zL)c;L@Ppr&O6D0pr z?{BDod!X?S`Ji@s?{)3-M)GOe&ysli{OWrYl@r#Ln=2`d+F+a@zmGq-hIDLY( zeg10hS!=EB^H6%fOzm^#2Kq5qL+SnUs0-2?kJ&KHNWV(&m!EulV8fc+_s4VoT6(`c zx-Qr>czHIfMfk22PP^`>k3A9I*BGrO#WUN!JH-pmQUn6blv zZe`va&W?K3Tz0EkXBFkac9Jiq~O#fJ69S|QK_ zUQTyA9^intrBUI59`Lko%x9AE9xs({0uFf1+HHnDKrf8P<%RJ82fSjz1HCZbVKzL# z0k3beDi8F4m(!i`)ceL%iU9|_HG&6v46DMihRH&nfCFBw;DH{nv~G+St{>ol7ZCde zJrhqGVqBs;zyWWr*gNQ%c-&_g;kIc%S4bQ6BxNBnPv*bCs{7f!olxiUWBfnO~31YOv< z)Bb=Dc;E-b4nP<7=T$!7fv*eypbLDj@&OP0uY`Zl1^>kkxqyGb1Am3!gD&Lfg%5b( zuhEr#fiCcxJ<10>@V5v)=%Rgc`W5&GJn-l4ugV8q_?4IZ01x~X-4s6PqFm5{U7>uy z1Aj|bg%7%D&z*h>e82-=m-0au<$K`+9{6jde9(oTd+`r=;I~M-0=mHWvR}Xhe~Z{Z z=mOu1f4~F3xmvX|pbP)+D|DUm2R!iC%~SZG3w*Eo10MLbH=k>aA3zuOhjz?aKH!00 ze7@?BK^J&l_6K+qU&b$>Yw|DcqqBUBcYu$4(1rcE>2DnYW1Q4a+RwTV?c*ij!GGb; zXctgk5)Gnq=%dI#pc{u$58H(n+T|oAr*P-s_HAAL5w*4xap2r@jkU_n7pNF?V~yFL zxF-UgqoqFj`EK+M%2jk<$X4-cM>=w;*<2|K#&<+RR}yY>wuabvwo}h{$y!QE7p+H^ z{Yer>7(aJeFfGXMJ6ib9@^c2J!2P-u?aba|)6g6A1iirypifo77Sh*0H-{_B>9J3R z(~+U?PyDT<)$}MO9{R!N4^%&h{t^8j`f;yuHQMpMWXtvROQBy*(ytA^T>HVCCB}F|m$+`8>aPOx z-TE!BT7>VzFF^->=}IqjeXhdnfPPRrm1t2vXvX1r%0&9Xdr59AKWEt6`$6aldPDu8 zPa_@LNU~1bggn~SPw4|TbNVCteNR7X2Q^-^%>m<;{Z!ISUoB~Sr1W+>$)5G5(fFks zS@1Q+&$~Uf+WkF*KKvtS@R`yQ~Wx_;+(KF?ww|?wC7nvWT5>kC<#fc6z%X68$Ok1ijTQ z6nhYT8k~mm@)XDDPjyE+a(&o7IT+8C^KK$s>Q527K3AqDA3;{kPll27#&o^~ZD7`_SstSGR`Q)dY!`0#R=SKQxbn_<3m?(m|OVW5g!Md*& zcflFYm6qodI+5olZF>^`BI}Kd;r7a{KUEs*Y8&yo7cb22ArbTjJwb11ccD*J9r}*> zyt|$XS8aewhpyjzFWsb<)<$@V+ItT7s7Qm}kVd{_BQo^1KM9rQ1B~%hH=_7*%DwdS z)*Jg8`WbJ%b0Gb>_?&2 zz}U=V=G`%2;@G1IoXL2T!;xduTTCkR9q#KH=+?mrl5`-^FWR z_-p@%Kb)|C!;v$RCp^@p(ct&-?gwvLGH?H!0mnYQ@!gm2Zupfg(>ML;znilE zp0+CMpstmfJN}rG)$)g}8Qb!^H|Blv_X)!vdcI-ZU1u8nPg+`%`Sa5zO&D;>6NbF* znf=51`}zknPa6L=(>Fu^7t0NKJod~%nWru+ZLIw5nTzjXr9b_3BcXflywepi}JG_p;C`^d#l9{YnKXKQt1y~p-r#f$$sl=;~6 zlQZ|f>AwvN9y_a{;-Uu{tUBnP^sBK}niqcbP&Pl0SOd3H=S?^@bM%wj8b12VFB(!l ze80f~Vt}*%rgbI%mFE=RJM0E$rOnr27-wBmv-xbjWa%>%EKRPu2H+xg1&aG-m^VgE z(zQ-cdejvSLeG=F4zdM*71Us$oQMblpim*y)F8-1vf zxtjmi=smdBjpi!&7jeFV>FOjqmS3A-VB6;_+Q96AH=sA@33>}uh&_m1sHz2WNkW^X zny1pL2TIS~>{abQO9tluk$%M$fpr$j&?C38hV4Cptol6U+8mpSJkcUVV>C6&|bOeO?jGqzG8RRr6bCR-k>Mw4YZ+8P3ygp zPOz}}8`8?(hLHS5(~ns;mc#bS>!b$LPmPOs zB;ao2b(3UVgt$if!HZnRF$R^$f8g(RLI?gHSn5JAG}bW=>OA8j$gfRp_wsQO^aQ=> z%aq=rPbClAxQK4?d${v3PHH1EW86x2F)l)SR2xXX;WjQhLOWICpSulP$*|tk9ESBS zw_WUUG}4Nx6|>`Z<`n!5dV=1X#ebpC-CYN-{uSe*$a>q0$3>zi=nZ;;KE209>Rmt? zt*=~4Ka7DGe+i{I;2zTIuKF8!T(q*d>X~L z2=--Q&*n@RgaKJj_KIq08qn!pF_Fp! z+qBf4jx0RwjT8kC`?{p9w40QF?l#QSVE10@k`%Ump3ml+ilsg7FZ>O9g5H|@E4@LV zs$%nUG;O72UXRnMPjOx>>ymg}%3-3IX}G0Bna(vu)^$n4YZ}Ia8e+F~Nyv*7^Ek&?mn6?C{5~U={v-_JPm&9$F(XR1WL4MA5PI)-aY12PV z^qjWb^2HV9RVCFWW$jtA7H*HjEzd8)mr<|!-m1=1NxMnKD`u$kS<(VCjq~T4TV$Qp zJN9!&oP?PVnLc)AMND%)lu8ib1LsSvD_4B9MYf-}1~}lQovrXd5BSb=+5iW>I&riIw?1dH`Im)IN+rXRd^^Dcsbn}FMLiL;DGnlkCa?M4|sG=rEzJ>Q{aGC zENRdKUQRbV9^imiTcpZExxmvL=d=M1cJkT@o9OtwF4tVev&@=J0L554Bet-iW z;6M*)tsCPh{Tb(;i68bc?$S5$#6JNKJ9XLtm&^Eo2Y%lfN{{ew*p<`%fDd@!>t`x_ z(1ksCl@EB}r(LMW zxlol4y5Qfde82-=7r8Zq4{3+c4m;%sc;E-benA)h__+jzE}Bx2mYFA z3LkV~zwmD-|9}TR`cu#a9`xYE2R!hR54yldJ&@1#!|Q_3Z{z)!F8w&*pf{%-JN*IY zM)3REbZYU{xnccMxRG<46VunqxnU9qj#KmI&1vm>{{=djAJk89qjzYos^1IQDqihK ztGix*v$;|fjQ1!wFATA)FX4Q(UOK*W!}wHFmY*~1?dPRHPtY6e0Qyw&Xd!($&J7D? z8Shb?@^VY}lbcB{@}(>u$G15*EIH*UjrUNw*)Wr1yT`d9HLPF8yL_A*7D;cG_g}Qm{Wvk$dp`(0L2sx(^l7AB&kZ|hGv~!~ZrBYVZi{&yE0pOxH|$2T;u{Ih&4wA> zYWJH+cg~=&op<;AH2Yf?`5XM$KQ}BsozA0Gq$EDIl+@+iFto#Hm+RhD?K0YHJYVAZ z4$nz=Zn1I`*S>`*vTs3ReXz94!`s&`gAV+=d58-=f8T;tZM*dv{VDVWz10m>dV@X{ zlm5Pi-Ks20;m{lO1ib~sf1ytc%5J&z>QAxGEAskx`#P`PQh^RG6ncZ6pf?l)eR}U( zXxYfH)_n_j?#Dg_=e`BxGhVcP3r8^!1uwm+T(v*Wd!Gj6MR?G*73n5#keG7xBV18bugLmi!?H>)} zbhB|iL;5|$BUL&u)@2-HEyUv*{;mrh_0|n76ge|Izw_wc0Jo{PS+7 zr;^RX?%keO6*l*;dsl$opeN`J{tJDoTJt`I6pP*{9f#hqZy|QQjV7J(&s%TM2Devk zdQ+aZ7oVpp?JV>Lc|f0<@qN|T$lqE>cg?xi%^CF686RAq_ri%~n-`xpFfW(vo^7A^ zN<%NFQToTa{Np2BG4B2&BGlFYxzdSkj?dQ;d; zZtn{0Zy~Z(^qZeh^=y5-M|IVDRFBL~aNBvl1=~Yfne(j1Q0BbJt8Fb{*+A+d%RS)y_N53ww*s3ww)l-E0_Sa9$X% zL2(9!&F5n5T><_EJwb1}_%HOiyKC*GH_R__d*!A#HICYQ=a---=nZ;;KE3Ccl)qWe z3xhx5d@#%}A&q=4Bl7&x=&tN*9K7^qJul2nZ($0G&ffBu{f+0Bbm=es`K9+%Qa<>=y6(VSwLZ2js+uhZ9^imCSJvf&9`KjbcjY+%4{*R+cY&-&ZBy=c zqe})J;DEP6zF!M^;qvTwfCFCh0#zR90dE+6SDpjP103**FH&*=y)d4=Jiq~OMNrlo zOSxgZaklya4tT|j6dvdSZ+Uk+9^imCSJnrE9`H16J#DeH?5hws;OS>5xqu$U&Yvda^2CLY!?OSxe@yF6PQe8OKqFN|leAK*|P;6M-QVcpgn zp2K?Q{RZ$u?z=c+U5VWvpnupu=l~z^CO-T^{2O)$`)Y$P@W3C9b>6}U%6HlY$_G5~ z*UT4t$G#b{Loa;51HV@AK^Ocx?F;1t9{6i2l>9&!a`VCmJn#ck)P5$=1)dlGfCs)V z?F8teeS#f3uk3mKfnWjU6$xi_yE4A z{RlkpnyAMn6mQy}f1@B#jveu(k`5BwJCA3zuK z_reD}@Y4hzbb;r^Kj4ACMeHAR(XM#OAMn6Oe-669_p%?r10VJUy5Jvlkk9ht`67%P zFkcjS+dh6kx$qzO6Z{hNhSR$7<=xeL;<40I@qUSENymHdmsl_RB_wXnQ}Y9XfXn<2 z3W*SNeO6He3_5rYs+;6S@4{R~>V<404&7%@M<|E0rgB41A@={x!zps>|bth#nW?3rok4SIs!U-m-SHl2RFt|irluEJLPCDe6f9`#4XFC>l(z58-mZ^pWN;qwRN6XF&T znVK{x$1GT&!UpE)&; zO}MbUtU6d*oxilavb1Q|*6Ov^*4A{gg@IHo;`VZ2%0udJ%441AQ{?0QLjyTNc~NDJR$P%uoH(omXw#) zERI7Q+MIY1TxxQH$b++39xBklOoH*Cjzo;HDG#Z?DG%{;UF75>XIjRRlHk&c^2+M` zqLQkL(t>49K#%ksK}*ex3(ZFDz$o%?>Ar3FZV6K!Qh&$;u)4?zX~d>H3TvvW%NOTY zRF+p%Av1XKkQxFG*u>IY#Lh>hhB0uZ(oU__5idC0ha@7a&XU+hbk zF-~|jL#+Gp@LYxGth%>k--pcG;`s{CiC*(2cuvS5V{M@y@5h^#^m~IZw=rtnRN40- zv3{DohdtfxxhOXMuA;UCbTH0ocBALqkJp~(EbY`><2znvjCDNLed)13XZ=m&=dAJG z{+tCpL2sx(^r_NUkgQMMj6BWI+rdUUk90px`jVRj0MEmCFOM|xO*+Pf(%bD_mELG& z35`#uCEaZNyvL_jyZ9}n#?+U4dqRlAJ#+ByG;`83QcTDj!2aCsi!Ns7DC^VGnk z`{*jkb?!jlcDgz*U*fuHsy(io-M)4ibl~5C>2CC{%~5>I{Fio9u03t7RoiQ>CkHkE zbtB=@_Z34Dw>d9_zppru=Dzsn?cYp~>8_?9%g-4UwmL6gT{|K6%ryHq_ovVk^roLF z_8@j))GqW(ho0J_x0gk461P)tKczZwJ)A-5O3hnBZ!Ta?v`(Lf-k>Mwt$C)>8}zxm zE8;dLWS-d9&|Y2Tq7b+BQZ8V-yLxe#54}N8&>Pxa=reA@9gN_mHx$GDjJMwQ-u(j5 z6Z8goK%Xidl6I2g8#d5aDQIrLn9f=MEzj{s4LG0Y+5`+flHTBN?(Jl_w1G+C>!{3j zA^@%*hf0gw*xzbTq~}E$=WM5ZOSS>;_J@W~u7T$yiflP<)P_5zE_P%y%Izyx8fVcn zK407E*ogWGUjn`adIN{;1z_#UsvG|mZ@eJvLV`HBHY`bYn9(X;CjB#lV>ULZfOeJ=`It;Sc^iibV@FZ2dIL2u1J z6#Ec;s(Ri}>$vaV9Ii8ef8h&DI-KKnh3_qFcXJFm_vMNd_L1&dA0oitTX;W-f9^KS zWw6b|?%mdNyX~KF<84p72faa0&|97OFZ8MERZRQLtlwLpbZB$TdK)9caoguWS;l!i zmUB)>Z)3HeCh^Z(Z|raU98L4 zUf&q|XK`m%aY0dV7kz7i%VfP6=jS=bQ2{xB7yF2DZXnJ<^g7RwY4ZM=diwFX4qeH| z1||)nBU*IV{lj(rercR%j9AZ?ezVAB+{4791hng*gZ80$o*TU*a}~J`*gw4O6B$QI z>^hF(oug{^Xte!RUgtWv?L&enmRos5J}|zQVpdm46-K=H+M_Vi`v%y`|9jm(Js0 ziUaBV=g4|vy6kUmdQ&`gAzSF8^-Y=-X2#=6ub1<*B=!K??YCKP#<_>Wr}MlgF9s(~ znL06N=Jc~?O`OT6#ub%R1`DgpE0^V06jT>`AzAL{0U>opYzP)yTs}z#zk3R-{cA=@|%xg8aA zo5i|gepBgVJ}B>PDu6kdRj?$Onq8HeQyMIz0buH+lG0#DmCba96qhd!4hfc)Tv$*% zL>r>fagPg177o!=aYMAhqtl0Ia<6JgN0#i<@+II)U@wqBdF7(23OWq6YVdq+HTHrU z`Bm^Guf>7647{suikZ-GThZ_uaWmcK8)ax*wj(v0to zKgH>v(GTaLs<{zOyGsD^EjxT)`~dTbQvg(?=GW*OE8+RI(OM7szIYFU_js2yXLhdz0RvC+JO=b{G0o;-L4*^X@YAq|yUaI&}T!d+Eknk=aWkzk4JNy&;W! z$wp-8ZGRGKSZ`~!ms9SgpSRxdemSzyGv2HlNh9 zYj{4%dcC{q5v^Q(>WjwvIV&9A?|yADIBqA`kUazbAB4c!{r>zA+rKR=s+^l;yFrQT zy77Frn$zaI174g;=k;mYXCG;q55MxehNaJ*ZqRw|#Pc(Mdrn}&qql!#UGv0*motvZe5LS|M_;de>EThC zf7x*8SEb|MTYe4m8`}Enb(^l-cyvzM%>y^(e0z7(wWnR1Q}J=XO&fa-$f@kIDvNng zKjxO^!9Mx>gy9c8->~kkGY$SHEiK9X`Dv3T3^?TpLmv0c{$c%n{ezh&jepyahr-gd z{x6mr@_6i-gECKDSlU?m+cO)9Mq|(Z_hdfw&RY}i9Qg#(m~h>Px7IiRE+uPA;Oz#Y zVbEk6$Na7|n`n?s_O0-f$Npf**;?yZ?^*R`#gF|ul-cvM(U~b1ebI2z{?|2h{pmj& zE`IyxrVd7YedE}1k9V7papK<_NTyt0L9Ie}c# zVHmbkYe>z0{<*0WlBLh&9Pa=0tiK$^-#4@e;3Br?CYlQK#uWHXR1aN!xgn6lx_SP& z=f-Q=MKablOG!yd=}OBO_oo|Se)!uD9H>s?Z(n)%gf3LCgND-RiEiTy!NI{7RxC82 z_N_k)$}59a)q{hzmD)a8|Ma4Q!u0v+BMX8fMiiwNjUF{>cwzd8F@;4%!7=IchZP2k zP7N*?IdV+?(EO3<>9zFR>kNf_X{z~C*3Z6U_>ZGq&?K$$*`M%J@M;ZnM|)6!J};b= znNI%8J`Wza6vc;%v%oXMQU8fN1D^Rd^BL0`@SX9%`H6mKd}_h6@|tRGaC-VME8#e= z?QNbyzBLk!u~+Tjbyx^<=c@0=7Rz^**U9&k*U5LA>$b`F5#F$WClvVMIEmI{hC|?| z_W7x-UtjFTs`))_@PY3!Z#mcgUF9(4gN;k>zf$Q6aKIZ~tnfh30H#07yW8;q2fQsS z&o$OpfgbQQ?R}$1Gs_b=;OW(>JkSH)^6qv#zyWU!%99v)!@Jq}1RU^ct5kWQ7sj)f z2RPu3K3(Y<^ul<*H#$1h4{*R+A$9?Jz+2wkjt4m4!Ja@5c$)UIaf$K(2Ry)m9@4|R zh4J`1+_2L=WL0cfTV|;G0Ur8y%8AQme88Ld=gD`J#r|Ojp7;U}eEl4S54w=E(=Jdx z;DH|)Cip@Z_^?aV3;2Ks{@gRvcbq{N`tsr*@W3w?`v6^(4?52B0T28Yf)Bdj+o^x> z4|w3umG%a7fd@S}%LhF0*PN#02fD!b;vew9-y-;+3;Tl|Im-t;@OAhX_z=JG)W5(3 zzfS58x{yEo!&yGyfsghYd;rf&|9}TR=z}isAqV8M{`mb0`h|Ytf6ZI%{R7H{{Gku0 zK1Wce!QYXl?pk|*S|a|A^wgx4$?VhoETh+6V|-s6SR#5_UF#l9n;YP1CS7E)7t>XB;BYnCQs=lLhCDG#dD-wst9>#hm zdUm0C`l+-ImVe&!hLGRQBs-R$GcY#K`Et>Ul7i4LQgYS1-SfV&E?Z(Je!S`CH=i)% z-SU=-qv03Nf7qtqXz<8~-k>Mw4R!#1D)<(X^Rt_QODnFkwWeb%^S|L7w<~-{`Z5>! z58tsj*z{Icn7H1)BBpfV(`!AY{?M;KvyM|c!*`??$#cBCF zo+^s#uP%Cn9m8&6#~=p#HqxQnX#MtIOgm1ZbduQd@x%+h6Ae3cen)z+@QZwuA+ce{ zmi<+^W?PkY}EyWttKto?9cKqKjTa5N+tHcdr$G>!If9b0( zr&WJoz)w>#=pn9qSK05H_hPf-=3qPRSonn<>y3(k@Z*f9=bSb%ceeFI(&h6nq@}@5 zxSg5i??|()45UI3TgyviStHxA;nz}sQywp$Wjt@{A}4D(d>xiYb!9v9>D@R3<2iA$12r*ok@{szQ@<T#@{-!(zi#$Y5PD-Xc76q5l&?CPp7@xXNH_%dN#ffHP<1`m}&`hd1 zUO(9e9b3Ybht%Jc#}JW+$jM2~lt)2LQAxQoH+nidF*F0-I|&$EPQWJf0-d+`n*a4aZs&FO>wQCnrg(JQC?*I--9mjv|i}oJ_}%HsvApH|24)$V24h zBsC*@=IklCQ;kPDI?JFsSX)g~LY37eg{28St2*h&l3pe4={y2v`{39b`dbq*UYqie z`kV5&R^%aaa*|^_?qwI37nLk130B6~Y?x%GC5UGdpo`0-J-veF)>$4LTSKZf5#zNf z52?Q?kLyGpA}1%g8G#?pnvy$!8$0q@C%5#XdeFIxG*4t>GAJBF1Y|9#Vf( z9@mRJL{3g}un+jk;$T&=6J}?p`TZQrf%{d&)-n&VCStrc$y`)XDMUS^3BidDPKOmIueyz-N2L8%%jf{Y`m1_^{f)Epl?w zg*>W?3o3&7^w1w?148E(Rs>V&sXtCUD<4lu`!SDhvOGAphC{817_UuvNc~NDJS6fE zIXTHe9yLqyxo@edjCEitgwC3iI;|isi*j;6>z+g&oWt@^Aw2##47cKlO?gQDO?f;l z@(?*WNkSgtFZ7bGJgz=Q{DofA#fN9*;}=on(bozbC+9eUBBW=lMkjR^pSTkNE>hOiDDpTm60%30 zDG#Z?DUZiQ9wH|vI^o_Mp9@?fnr2eKn zo)meAoSZZvkE%t%(qMIYnKM6HdRBsXR=R^^ynY+qblrV@R9wkoueQs26#NoSdW}kBaiD zV18-I{K|sLxR!v-AiUJ6@#9(f_%2HO!DqwA8%%jf{Y`mn5P684oOB_N#8yjbT1Tvx zdMAoJdODeoA#KV->Tk-ULF6HFa*~2P5?dYAG3$e#k0Os=PNri>oAQwQoAPKBd5D~x zq#%!yMOEdc^iY>yQe9A0=!Ei4PbniLa+%Xh%7XMpFM$;kn)YZEc^v3nyl0Ln52?Q? zj~mpwdtKz@Bmj9>=hpM%=yW?`{BdU#c^vFyI)=0<52?Q?j~hiEA}1#)$b(<+FIYzJ z_v7ql`2GHZW%Po-9oEJj%{E!aoA zcve1+6L|#aCXYWjwg&nJK-|HUht%Jc$1g-4u#lphB8Lq z?J)=a9fv%m{-!)uh&*5?|8SQ_Q84bUVg`?Nc2m4t%-Ym#rO1ObU>^rs?1Q#M#vJq( zhdiYIraV@PJYXj;d&ncf<@g=3{^N2Nd0730wnoPs^p73#koueQxLxD{J9*7r9@g<` z%!LzRM~qKPJmk?++7CSrhIH85ZVpI*7e$5QHdC0 z{j`1`@_uNxk7k0${^-L<&fISYPIuoYZLX6#Ybw2#tF9_7udd3Ep*%Mb>MmQkPmD*8 zZge8uL;X-6)GuwSsvqhN8s@qusvp)nO?Bdf!1qkgCl>Zi*- zchnmNPMbI@kWY16qE=)isybsV!}a4fDV}y3e8d`~ey9)X2Yl2UY1A*g&LZI|(m67_ zMt{cscR81apR?HiqJ?3)J~b#Z}vk z^MhI6>nI=R0^yt>UCs%@`9U}z2 zk z$c)W13KKdf=mnA+%g-4+&k6d2lB+&X^}C3j`0=KTTh#d+Y1?Bvr=w+I;^%a%B1eRt zpf~UfeX2BnukPf{$kQ}F-|0pp&1(|BrytLi+$jJ!&k67MknZp5_)2fLQzOgYtD~nU zI$vdK(y>YW6M`<0)$aKl8qUDjK(|uTe=mAlo@&fD=n^~e<4w1SzSg`So8Hn&64zT6 zRSf?7Ix&iRM&j8;M3KOEd7l2QSTX zCkFu8wp! zTbkdk8Sug{__Ll{&G~f~zGbWnHS^^=)@C|&gFRoqcg<~sL0{nc-M2N(_G(S@c)*_K z6xB!YyHM+4PfPvHe5t>gmin7%slTMDI7P2PeV5xzKUiuXJOeZy&I% zXQo-c1aGFLJToojnQ1A{OiOuYy1R{DFB)ZA`RQt;!}hvA2Oi~hRN z*RZVo_Ci|VyBg^*{cbXrL;ZRoZNl?d&kD~Rh2_ze&PliC_cGF9`4XtgzgKBM=JIKL9-P%<9~!^jAD4gE{> z>p_#4!@F%V%4A>EZ@tboj;x!m#*t>cRK}5)xQ`>ZoUF!=Yfg+jj;s?p7>@*&xzKAG zlc#u=apb(G?P-7c0F% zpNd`}m%bvjDNLKwX`91o`_-Q%iE$*-|Igl+09I98{of=k*L@diT|&h+ZC!$Z1S5G_ zKpz$r0k>+!m;{4H!aoE>?I*8l{hrpnZrCa))#6fHw-yx=7QfGDt6#0QmAbUF+7>M? zpS2bJZ26xvbAESw_r7=Edqg43g_oJRbI!Rlzcb6ZGjnGS^pi?8uCD zkorY#)8|Oya{r_gay?pOBvENjw~-ucFYwm~mt)KDL2u9#^p=tO3w?gpxrrK~;JSwP zDq3&uxlmm1__A;7A9{nHpf{a6%AeFb%c@^t)lZ_fZMLd!FYo?N(?!z;QCQcvuMmDC z>Bn^!7c(7>?PPk*oPeBY_N|&&n}l&p5x{5As$qqvk1s%S^Q3B z|2Qzd)*&Bp?|Q#*9d7dj__b52Xq8_qX{o2572Kb?`*Xh-$0oGvc+Kc$i$Hom6y=C^0L%-W+w zZ=GV#imUTk{NJkgwZ4}8J)Yjy-CKM+&3c2LptsDWQjdN0uD#K+e&n%Vl?~dR*orF8g+!Z@9Q0*R_B9^LKb2wq4w~e1+0+JE`WGB)!3T?z>UcoNrrv{%kf?E)V?go-1eZ~jV{O9zJJwQjz>h4<2xkZ3$5d{G|ywydMDKnN;-q}1^o8!PwS~+SZMEVd1-k2~zAO?RxLjYbKClpRnAb%)M!7{fhAfnCgg+}cpB>KS zINT2ZNZD|l?vaB&Do6V5>hN-m_+s6frjOJ(aaF^6q2tB&2Y&m!{Ql|(F z=lS}BlX|^wPo1MJ^e<98*UzwXv{#%yww|JV*VPf{X#Z-#{NBe8oAl(16I;hI!;rgM z#|=5Ub@|Un&gXWfW9UAI_Z|Lv;@HcEuWVi4K=x58@jUS}4@IT;_Ylb% zO#F18`BT3lxzCWSuM5q-`(IN(>(08yo31^sf%(6fdZ>5UA9h=I$qB8?DGkd%e)^7a z+Z=m9&&&1mdnpaQ4`02{L#uWlTVM82>vBrN^2N*csV{4IXXX4aH#AZj8u#6%rnhrYF9{bj+$39-TV#5&+ zHT?D1bDJ(%_^rmjmM^O3H0U2w^L)nqUhQ-LK3KlnNV>1^5Sj$vWB-L0WfJ8V4O{t# zoBm%t%Q@*kU*#zezEbKh{keJj0V8JZTHy@Kp7DO$xVNsj`9Y5V{G$hsTff~dy$7B7 zA;oiAwyrDgnb~1o|Ch;6=n`?B^I59uBE&e-0L>Blxg1Iu1L_wb7@%Jlw` zbX!3>=KIbf8X@9#s^b@XCeC|tQ14ngZ~MRAeY1z_W$@y5SDm9R<6vuuAdD`^=h6hr z#^!jAwjK8z?IFdSqaDO%YYBVK(cW6J?8~P)N857F(B|{BU2s&J;0dc33G03hXK1sl z+snQ=N1Kix{8Y}-PM==vIoh-%XIn>sr~bG|!{@fgxRbqai5rvcTY8c{mpOg?Y3hBW zeZ^zieeD;@4ottM=R53I{pX}+OR{|DXotmz-Q#|!k|K}}oTr@mhF+JQ&7*gb1RvXK_2)T2mARz2fmD)vkQ6P zvj*)>{cxFczBuT>mz;T`(huahe9J4me4qm#^b2_|-w+=k=)ea$$V0es@DK+VUR#NB zgL8SS{-nzh=#k!_UX&d|M4$)%txr7ZE05q0>IeLw2mjJ1H9zDc-$6ZrAN1h2S3aZO zpCA|fL4AQA^x(hsWnF(D7wHe;2!7Cmf61$wA9C^hD1Oj`e~s`%F47JCLN9ne=)rGG z{fAuO9>ouO@Ye`GP;d?3<7Ay<+ z{fovL7{B19x%DhrFm6i@LvPR%^oDW(ed;{YIndUxSG)P;@ZnFn;oQExCHk*~amdB? zTGqMH>*!qQbwnRE4#s-hhkjh{KM9emx%IiwAc%aanI_ z9A4VpS1D@(Z_Z3obH15h+tSK*z4qOk(2eJoIrBW;`|vX!+z+DPLq7<+AN?cxKlGzf zb_Lq;q11*iqaS}c)>wA8!Z@rAv5%MU9>q;wBmLq}!ul$=?51Je!-mf_kIw1g5HpS=u?GLE1T%e!D&w|i}kkMYK{y0?h*D1 z)~h3YC4~E2t+(3y9?-2V5E`t)@mKj{s6g5EMqwcemlooi*Q^tuSR;l*_GQHl7C zfOMCH3t1m}C5>sxI%m=w*Arb=qUsyhHS{xKdehwQ_g|c({-ihP33@|+34Ll6@V*@_ zt3@5;aJW^4KlJSVL*9)pjqBsRi1>P4JHfxf`bPHa(6TqwFS@?fkQDw!)i`!`wo}f465&A^NySi$5Ls%Ux|2>njf8tt>OInPCs#Y=Ayf0*Y8{%q zU#_9ZIQ@xB!{yX_g|9>NQn-Hb!gXUx@wsVZDP`6GYtyYmtDshVml4zplMPOL0yod? z=q@FxTQsj(ht}LueP;FO=C)CzTB}=Y4m)gQOZBL+Ev>C>W2?_Rw56?eOxujnqsLAk zF@1D(^*s6=eD>_KwrG_H6K~d`9cx+D)ZirN>wU;}CcnS^2}0%%Pn|M_cAjtR;)Q5q z{ZR#l!k&3+0TOPN^&Uh2px3=5#Z7-rujfj>qSv2gewTY48mEJ%Gz-4ij;tguqyy`p zGLo)rf&TSmpab6q;e$Nz2iKv24t!O=*ZGG$@LASt%6>;WK?lB*g%9$;*ErbE2RiUA z6+XxVAFo5>3(o@`_|^#@{2iXZggw~vzbj3Ni= zM>;r9eBt?^2mjKf=7(IAkErK^9{lqrYJSK?c}70;)7|HT9{e>&OZp`p;1B8%=?6Xd zZxw#XMf#)oK@a{7!VkH~H_BHq{h$Xw+8@Y8zN7d-4}QppT%V;$O$LhvO@ey__~hxTB_KGuUoAN79eU5BL^IyA&*i zZlK(t-R(c?(6oxAC^`CyyABQg9{NGp{pcTqb_DuU^pDO1$%Aq6Q_0W!rdorJQqf^; zNP3Fwn+kWO^n?E$)^8~>Isc#^Op6@U%jD`1d8xw#^W-JWn`6IJxSsJ`y$+4{O^rWq z-blG*{IV`J>#k>ovf{Sj8_*l{1ijh+rS%4V>MZg;skg3jv&-R8p0FFkzNaOKb!Z45 z=qHm9k4>f$Hih&$w7|Zp8$+3#n{5AyQRUoYkJcDTBwv5Jpf~6Vddo=tg+4#)JcqSC zoF?zQd9>dA^X8v*UN*(^p*QFWdV_4}lh)6#w5&_0e%VsL5Z3kWLtZ;X13lxuASR+KN^dHTo)cByTnS1{zxl&@Q~Rb$e|Z8mCvjR7?uNI7 z>oeImb+Wr}DzIdnd3*qN5bPpg2zv?R3m7NCI05V<(6h_+;v3}h`|TheG#!*8Uw9d} zult(Xj}2}*BmLknL+lt9lIKEwhaA-R5D_07AE55~Rcl5C|H9iI7B`&QDzsN&;{%$T?IQO=+v(of@_c9~ zp(p4qE$uG!sdILAlVv^NdGDZb{n<)yeTKxD(reQcYKK6-m>nk;9s=f@Eq=E z!t|!!L-c;PpzTk3gPx!_?)X69)7ypEJ6tE?lt;`t+Z|6h=Swjj<@9T1k8_1d z8|gG#&5G{526m_{)FuCTVS@SD&+esrU0S!~>cbM>N?E?2s?uSiSLX4FF!lxH#@bB`QqufDL?Zv zExSzHGO%;Z4tuOsVWw}I_@JU~nD;HmWk2(L^VoaGynXUQMa%LU=9SfO96yianE#1? z{7c2((!O)eg0aiTeAW73%=fo_YYc~*CLT;_Z>*V7mL7Zb%xQ(*kcqWV{jt9Gmp>e@e)}9hq4xL78fu5!P+z-fZBy-2&otH^ zcyWF0_Rk(s`^~45wcEdOc}-(YNw=T z)ZX>b?Aj4Oys$R)!R57YFTSjH#7pPZ?z;E%+Vj^ORZE!GPW|?7wL87AYweG=-?R3m zM?Y8lqYsAEK6BC+YTrJ2zuLy@t7?D0+ZSu!y7!>kKi_q5?Vj(~)K2@$sM<46{Yvfn zMW3tvjwy!`fuug zKPbi~3q>Me>c6S~MHU^yW)Lt47zDOZ1n?cB-c#E@?iepish4=flJ;xkKQx~B^8Q!X znV-SHlmSx)Oc^j`z?1<~222?+Wx$jHQwB^KFlE4$f&N_vc-@To84OGr*qX}#4+aL; zG3t9c{sz{r%HqUby&QU+GHlr*?oE~bjnb)N_cxl_(lv8-H}7vW!u#j~{Ya0OZGktC z$Df>}_d%I=f@IfBD+O5KPAwC?^fZ1Jn%IRK2}Wt;CY|}Uq<*K4}6v7{_+Ak@TI5e{6U_}=hq+T zz&BLt3*>>%vd;0P6LjE93LoTwud>|F2RiVfenKAjEbB4l1umciALt+t;mUHCkN1~C zy~qAQ8EFSVk9rm?cl=!D2R-;V2tVYaoCnJv_(2c;ljZzR$VK^!;s-tW)4~tAD2GS~ z@`dMv9{lTsA99`NOFatmgC6`#PS)iLa)Db^`auu=HNp?Mwv=zk2|ge6;I~iF&xc&3 zA98~Hpa*}u@I$VHpQIzm4|?!deO*5va@&OuApqwohk_%p%}xf#iSu%E#5K@a{7!VkINk19W)2mid&b^0L} z>4%&kexL{c65)qjv{zB-2R-=L2tVZFxxw}e`3F7tYo_b;LoS{l#SeP$XM`Ve(f&p0 zAN1f)pP`=*xp+S01n~ns_=h$N{*n%)8|`zDAN1gd{RO$uUlc#+!4LV6i*$$a^Y`1f z*m?MVJGsWczZ=TEE#+d|_CV!>FnO|!c`H1Us zd0IpdgB*O{X1^FFZ}Z*XZ4_b0_yw{gUnn(LchDh8>3Y3E0Od8t4c2qqk)KPPu}9jb%N&bS<j1FJTafO^Sx){QJt{zto zo-_IbD#bq_x?KHWBlVqJ?!)#~(A>TU^@{-4w|c7FsK@4<(ZbYv2JM1I@I{_8igp<7 za^|T|-g$FA+4=IGg7>=Mdk)^4ys2S(fcHatlzxM$tX7sUif)$|JgoPZg8Q;=k29~7 z)-Ky32lYE#US*?B_wxo-4(@nh`x7rgYoDg2jvy8d&aKZTy4H{=ldRN)naMNcm@>3Cbhl}$qkyGqf^LNEth z#+R?~c-<~DNf}ucrTTV7*mSPHd^aya!aAl1a^ix(0~L za@0O|((a%gvaitdVrZW*KH}JkGG2`F5)o&?K0J;TxDWM}+CKcHiVo{r(rPvEVOa2UfZqVZ zj`0g#{oXzlJwb2CKlG`>%09ehHRAL+^rKaHELDO=`te@BXvd)^zQ-5Bh}U=VSGPk~ zk_^57uRe$VF_OwNOZoK1<(|uY@Y3ADyIX!3_95zVzqb!JvC7V{26MX|X&<5;M!TGm zb{Tde?7$4ht!4flFe;b4zZmzE{NBC|Rfa!QWK>BFE7SHJFTc%psN?=o+U38L z)-Ky32lYGirx1CmSDJLXrCnZezStRPr;)30_xDo&w0#(7AIm>f>_uqMndXu88~8=N zw`=bHW*zEth89r)g`S|d^cz}l&}XM!*9 zS?455Z(QH_$L&?vc#E!S{dZq>=m~m*o}f<^R(tc3ul}O(+s^${(|rg0Z2Y1x-QTeK zFLR~61Xs9=b~5Z-nQdR%{|L*vP|2b9F&04YV}Gc4u!4X2+sP=sY3}g!Y{_@IzTHaY z75(MkC^OV-=DlE(h7)dY>G!mqZ--$KUugf`-yV8`-qL@Q@*w(D7^P+g-UBfH81KCRQQx2^=q>rS)*JMx%k~+KmbGBD_VZr~r|wtb zYbb>A;I)J!Uw3H7+C|(k;+_}|T!NzOJ?kTAy?%{#QW^iE?GzEI+N)^$vj6Ur4n09{ zwzRv@r^aVglXb=&PXQ~-+FyrL*Q{PlH!*(p8*1f+m>`h>ya$} zOl1&B{B6Zz`bF!F>l*r*XubL03&M*HlCfpDsBh2{^oGF{1n~U_a>_Lgl!k_HeCd|Di-%SvUY)!5vK#h%_t10SO!lmKaOJog|K|@X zy(4e`&Z-B_{YS$uXEm-`|9=Zt>{WJUWBR7|S5Ev%edFf_EUM=;=%316;dp2^YuF2& z3J=cDn6o;3`FZHiulw?oxxbu(i}o8x_D4a@QpMEG4AE~nnBvf;UBC)JfppUE-Y|Ak-Rg&R&)=v_B$%voj)ux$G} zB_!F%x_R!|XUAde$0NI@WRMkBlQ!XQ?l&5jGE%;nr1?6j(5oGUDKfSeI zGdjE4=5!z2Hm_^zM54O2xuyEd>e0<@qeit>x7HkX*vOXZQDa+LTieD~pLu9YTkDv% z8KXy!ojzjv=<4cu^gHsJ3*SM;chRPKS2uRhsxN(NX`5I7QFtcH)`FdvW`z)|be*62_T8gZWIXZ^L*K z#+QQM^)MgXkv}E(Y;t#{7YF+0Q#EN}ZMuDutUnev^PYY`O}}5)YVEI-nM~qJqYW3mUIDp0H#5f>+phMUZAo3`1|w6ZD3>K%Xk?taF90-rsb%&w%u5m65J8CEEFVYIPuCA^! zi)bslG5dn<_Rd++8D2nu@(+8DWWH7W-Xn86^xh+fMn5iZ49bU>@HTHCk3S=2b;CKj zEVj?m?wa$ooBUp8pSR}I8t>QMRcmTNNj}hlZ_Qbn z5AqZ-{R!?p0y^;7?V1nrz-L*@)!PrA2RiVbJX7;Q9{3su`}sfzzBOlSKF9+f?>)j7 zo(DSc)rg)T&*k$!4|L#zej(508{*3!=)ea$$V0esu*=7LPoUiFN(GY3WL2lmALxN= zFx{L_<_A6a=grpqkPDoG=?6dP!M{fMAs5dL<^%ko2mi@k`uUKH=SJ~^9{g$Hhg_r| z_yQL^AN1f)&e6|@T;LbQ4|?#|bZdUdMY^N-K@a|R;fGw*r(iip`auu=q_iK93;cm& zF#n(jKiVJ2#dD+hK@Wb&hg_r|=|DWEpKX4$bFlf-4X^szJMaZ@gkB&IYod8g$(~fR z^tborw7*Zdy=4DD<_^V8ejsyFAC_kGLk?_5`=4R*IvRDlpKs9aonk{GtnWts#oA;w zN16II@$#B-akFfGo}-Mvru<)IH!^;~tG}-)hn}FfjFbcDQ{%CY^!4l2E;bxK+%xy( z#)SFs?fqXvY;&ULcjWpM4fA=wyLa{oz)T+Q8&zr7bdL2tkv z`cz^5_P&0Yt0(m>zSbMJI|tB@FX$!e+k3=oYUi)gn`dsB_DndSY#n`jpG$AvZ|}qO zrn#MG^cxSi`x_`XXn*_9xA!~JyWWmj@0}aZEwdKo&>s3h^n2(BVfUkdME{3=ILfX; zKRA@y@MZMlvG&HYyH&cv+K}|g@@*B|k92>P{J*e%D@R5oiu1FG>Qh?epk9W`+l;@x zUo7|qbKKwiLFfs3L;j&p6%PIOe!JBiSID>bS3E8sB)qqP zo?U!f#qF}1YaYa_KElhieX*>4h5Ikv9%lwVuGYjdUm+LTWn1K+erNt&TsvRLvkRe( zs^9Ts^y9U!q9^DrZRv6VeJXrXqsMEU@E*A$5YCMvmruUpuYI)!(YjauMYhWR$31<=)r=eP}14C+N){p!J4&r?aMPm0mZSZg?@>%(wQ{=^0(0{zX+sKXw z{NkQL1Jme zEj>3({gBhp^ZBPoB#zINC;nW0VuI3;xa-239@*wE+t)vGg^EXsJ^7^S?J?NtA+LwQ!{h4voK3P-u@t2N%WW?{jv+|o` z-*33(^*vU8Oly|MRiqmpzVUA>_kVhqhOdOISuPb1&d(zcU*XHowyAgOy!kof0?U`5 zhaXtrWePH{TQ&D^dIp#4 zQS?jk{gT%#%lqXTmc;_|TrN#8ubbnV|01$LOtn&GMPeb7rY`W6kNQQJ@u35%9H2cz`*P*pHxAF;C)zu?Q$aWZZ-zz}g$@BDjm323qs`he9 zepkDhTeNGxq1T@!cicbcw``n_Qr4j%9a#UgPSTZ~mEF}XeowC?ALziBJpENQJ_>n? znEuQk?B@d=_|m78zsGx7K_2)l>rG|V<9VP1-%{a&Jn+pQ?B@d=_=Y||L_H7kz;|e1 z9UADsck;YC#RqvVpZ|HF1K*N;zoGab&*iK2` z10U)O5QJ@Y^?Pd?6Rl4VDY=gC6`f!VkH4ZWKT0!GEjpLoU)EEMIs&=)s>6e#ixWQT(6> z{|4cQT%r3J^0rN zKjeZRdPKPdKj^_f?`EBU$VL8x^&I@52mcb`hg_sPiXZggx1~RWT%pG7q`y#LFEDIZxv%eto zV&bL;OL#l<+4_^RtK^200j?Ol}h<@9ZWm_xT3prta~F^E`Bt>H%c_4eL4KhOX;8 zhV}~PU-Y;#@Eb|}VI=8Rb$J(Cg!^$u}gY|Zttm~`{k*m4&x=!t9uIS6YThH^u zji&r;V_0t+C<#dC9#ki!TI5XFR+GM3JbINgrb!*cA zDaT);G*t_bD5t@7u7?ET@eFZQIrgt}tuEWXf`8HFc(SMc4lBo+TR*|;4?Nom+V@B~ z9v0UA()-&n-G5W>apF3RpR&g($C6%@WBZ4>*V~+Q+>}Y93D99%D%3^IFf<@GywNd6r>?iD;D%1Ho^^Ex}`o?8GM)`^8OgyiH) zf(J)29{M7~Os?Gfm4eFeI(SI_9X#$6JOn2{mt{F6Ym;@bI$CJ<_m&^ z5#bYst#W)pY(8l_<-vn@Ln-uf@R0mFc-${|2u?w{4jwIY=X7_TJAHOn=j=H_q8#BS z#a20)*xI_fXSNl>3$Y(kKZtSxmn?TgTiZFl_#Ouj$-jfg1A>R(6qKmz%P|epCQO;w zFv;7np4;5r)-|)aBgnDo!_%dF+)1Jt4|Yqv96Tid4jw-eJOroUbG%5*?rP&&6C}wQ zo?HY^P~cH{>WkB)1Q~OL9Xure4jvB*9)eR)M0WWotc%$c{mb-EbbWcAMmV{Au-@&6&#s>ta zAY(QjbK1JQY2GGg!#K4d>fqCL__Y7i<>N&PG9K)DFSlj&-p%cI@R0mFc!*tX3r;~P z-u44sZjdHdcvJMZ;{^|XPFVREm@5GhaSk4mf8YUfTW~@ct{0DDy4+3C-yWC;4|)YF z_+mUV#D({%Ayn>iwaX3;Crp}7J?or~&h9zW3x29*pzdKK*YRT7y||Bb^ey9r{pUMG z-ffT8sVE?5<1V?TUsPs2fIx`Lc<{I_#%VEbo8DH>`(iv7Y^s&msZ=axiWZDlhmQVkzUc)|e*s zJ-*|*Yb5j@T>L$L{Bhe~3Vy!KQJ}w%+d@y!8}bi*>hL9m^;cIT&Qf~YO@+sk?vIfM z>jojf_&VNC5k|ZtM|rf~Zllh`J>%_|vhR}A?^1kN8D=(bx&I&1UGUP}`mWa>q}$TM zT;J*mZ`9-d`W<3Y&eF8{;5$SrYN2PmaVw7J^0|dvtdEl4WJwR>Kbs6egn5q;rs1^& z%wZ@0TkWgzMG0pv*Xx!zSi$ihRI2qooB*B;LYU(@oV>!NSMg~bW?PHXV>@9zm*j?Z zU*v}QX6jDFEzr6DPfhxbEf8JrjALjZ+`E%k$zfM^6>x4zWPFVEoghjtj znA7W(PjilgykSnS8-^VTyAgJzy}i~S?91T#53DB$uBYJgwLbyG^Z!qfJBV~MyzCzG zm4)`fcKz2>xq_SAS=*1vA*I=okOO}SpWV07J7o-(C$K?o2%ZCF79Wd_12HidXoMTdIKKNrw*s2on-gA<(72? ztqE!Gv8;P}ZAjj0xYUQMLh406=BWC{e5h~X?WFs(;bpEr-}5%7c+MYRT^`)Hot*b& zvP;F@d6VKj(TYCo58JN#8|g+X-+K-0(04uRTU_R6zh90bG=B^N1_6VB zLBJqj5HJWB1PlTO0fT@+z#w1{FbEg~3<3s$tq=hoWi;c3TcP4jmJI?10fT@+z#w1{ zFbEg~3<3rLgMdN6AYc$M2p9wm0!1QF*m$Dav)uC}S@*bWz2{yk!FMIbbKkv(?_Tho z3%+|v@1VbX!S^uuz6IaAVE;_)hY8_)Ch-VbtcmYl=zs!ihk^XvOZc}QcD1aJhx+o%ngLT1~y+Y)z`0{uySN6SJbf-U@=b_unh7Ibwm$kPNFMam{H}w07 z9R}`2Xyp3t1^7jM_oBJ=YJBa_lgKS38hV4CpttniQa(hVIy#8#Tg_mI#cOsPql>4yt+?t!epRklPNkXJ!?=SiOiguU0 z^7sL~5AC{_wHwL!DMzs0)V`OJUhF?&9}rUCJZU@jxbYKsSF7fh?wRMcO`p}-+BW^H zwpp~ZRf~rz+IuW9M90R9`7Z6(!Fz?AKtFcJ1=v_uxa{Gg4{>on=sI`^9q{#h*k2SprQ8IihT*|`!o}U( zt)z|MBrz9B`QRY%@a_jE&3`cIIl~Sfl79z}F9{wI^#*wG-kNi}+Gwwu*|Yf+j=0w} z%~yF$fqY*1EqU;W`bNVmBj|VVko-G%R0$q}Q;-jMG|!sV*{ycW4N~L|H#mHAaueo= zT^E9fx4u;5;EjrM@R0mFczjv#5S)Vi4j#Ha?e6R>Y=giC#aB74P(E)u77-r2A5oHi zaJ})x?2F{!A^CUkkbcn?oV?Frzrv%0P0%*Q{%3ng`QUxexcy+a)XTv`@((;9*A|=* zhO6*!HoKyZx4=!%HpTvD|Dydh(T>9Pwx{9d7;+HqG9HsD3ii>SB!uN8#a;r}akF_> z?c(b?o&&jfPFn0SJinw0M2W?7AQ#Vp-G}G1K9IL!Ts#MI@f^s)^Cxz2TM`>t!KSwA8^|7;&AIf%lH>< z*Yo=r|M-12%&ymOV*U90TG12qCJ;ONw5-YoYVDh>)OScvH#c2xRX+8tjjiL?4C-Dz zWuLp7s>p~QK|kKR3h!IhVpwB8D};4C_8t59NXz>8$o0oB9k=aEyVdKxh*giOBwkfE zVnD9^tqc>T!Vmg;hSOHtl2uJSHrgo1f5-m7U#xUgT$_LSH$cRU{W zemj-;ed}pD!;{=@h%RE`E!g*40+>n`FMH>2{s>Da5!M#@TQ_9md~qt`5!# ziaPIypUB@=FQXstQ#g>y`tY)Yl!+Dg&3V;6-&5!0!Oe^idvc6+^XI@%fp#5o&_1L` zhROSUljfFjHmihvO4hzhy5(^;aYM)1cxMs4yGR%o$O+>YwNIhu_U}^yzAf2>-k>Mw zEje224f@o1RBdsun_oA)fo$72?TX8r<BQ>eN9{c+Zl zx4;|F8}tOd*;0R@Pn|WcUsrm@M>%|z3V)t(!+sVMB5=UI4Lbg6;vG+R8C;(oRk14> z@PkO=k?I$1NAaUr?iCf`dSeOvE>K24?T<*D+_t|e?U%T@sXx0|)|(n1m2?K**P>E( z;HFcW2iH(`Pq#w?{E~?vDpU<>Yt_9$t8#pgPWFg*5{g zamBhQ$0)Zb$B>8et;1K5T{+|_#97>Lr2ev+!`^cIETxgJTeYKXP4=Q3BVMA#(RL{-mia2QSU7?|S_~x-BitdSiTHKm3*a0(;J^kXa&^ zrnVP_*$1F0-K8Q+m$tVmZL)*qd2f(tPQldX^V%vK=2SLzw9O&|u=2>69c`sQ)s=8a zd*``rhqQIfJiEF55bF?&jzgL;^Q=QG{kTJ{gKMe}vE<&ILtH-NGYA+23<88eXV*D% zX47F|a}GX}TMdJWLBJqT1Oh2-3+TV#uP2Xf*>skB1^u(EoykVSFiry+ zjNf1#6vk(8t_0RafgbC5Fit}crWHWZ<23eVkLi7Y#m&^ndwHTby9xF-#<1~5=l->upKdy&@o}jnn5mFwcTxfljZ#uo5 zaf8+y+$_EEIUw=%_E^OGzSfluMKv_*J!@0#@fD|f6?!^nD65D z>d}z*+pzJq{-ihP33|&&y9<44m`62PXWXImq{I8`aO#@Xi|NLrqKn@Mes@V2dP5lT z5)DV`ZCe6W#zjeQk6OR2SWLfYz46*Z{^izN|J}bCdV<~nCiIE$XXQqXCwc9Iu<`62 z2JYt6Zm<8d%16HE+V5?r&SUY?VV(3xo`!#p8E^&Hgui;kah z8hUPi`k=$U`s*X=Pd)DA9!f*c`ge4){}} zRk5g^)1ZGuP1mJ&+|cvzsXN#G^Lt$ik28*%+k44(4_v^$;=o(CWJ*2;k=?a)Xv8g(kRp1+s<^g%8szANrMuiktD zVh2)*6Q6&#ZsFxu^<3NXySkqL7@OF&dJjhjBR{(S@b~I=Uh%ijU6%Oz^lMkJSbiVz zUQz9omxldZf2(M47w;=;=w3inkVS=E8ZM{atFqy_XD8K_OP|Rx-2ZvcH*%@L3)hV) z#pkAtrSMGD_O@OZkt7ULiRYeumX?TLD7Loqq>74)f%KURuTXK*!)F=tMR^)`+k(&4 z4WNAOGJ>opx;?&aM)TZ`ZmaF!vuDR&!K=jei$60uyV~Y-AKW&t%i1dQU)|c=QhjFi z=;pRjqgtz5YYsbXWJ~p^u`R8wZDXs?JhY{)bxhlg(WA#sA2EG&b@e>@^}B*Xb!n3G z(}kMrj;cR_cEOUcj_3M>pQhK}xNYi+k=&gY3nr?m{&Jm18u%$X9onr&nwgIJPsAyD zPPY@!oZf5dvHA?)TLhiDOk}zxq0TS?regXcfy|e{g}K=w&9jj z^}3?(Y4>DttM1U@%uaF+YyI#nyD<0|dVMMQ;(n--xR8!r1jmza)z8lsNQ$Kke4qng zTKFIj{EdVCe4qp0I^lyn@LAS!)uZ8gpaWlWflepnfv<6}pAU54tGP|{K_2+5LAz5q zDs%D&I`Fj%ALO}w%PYKmpaWk<_#n^a8{*>w9r!i~ALN0raqtiyE}#Qnm6RjM1K;{` zzaBsbKF~oP!t2XjJgev?%IU6BUefYB&_j{ASPsDtdhln2A9C^hD1Oj` ze}nKtF7jO!DA#yC=)v!_*T{#|+bDj}gCF=nF47&w&+{wj7cjq)-q}4TlVu_Q!E%6d zh3D~^myI;W$?LrLq!wks01B6tQ=1e%R%Rcl$6?{78zekIyO0~#Wjq(r!ypIaPsye* zc^&dD_I!hue`k|+5zhV82F?^+`kcjY6EDxNi0j%OYCRLZyU;j&BdvqwUpN*l3;6wu z-b)z2;HA0ssBbWCOAbSC&=d4#OF4i(bspD|zJ9&h%`b-!_l*C#F=4*F<>p`YD`Aj? z?Zo<&9;cV}l>1og%K4XDZ~IW$=W_o^h+NH0XP#PH%F6yAEa7434SIs!Kn;DWaEjNx zUh3*ig|*%`5`iuC=>x%Uu!J#Ak9n6|dh>iwMC%6+C|g&~zi7Sf>uImT^rpFyoBrdn z-Zn7i(*E-Ip#pc#Oj2{cnO{3v{4bc7jpvqGi*lr#@!)W7*v*U14K-=~K^B?`?21N9z76oeb-@a%4oJP%j||^)ggm>Y66a zhJLSve$X02vZx<)T<0CUsD5xU;l}s{um0W-LQl{e@(+EgaB3xCU9}2vbUHJIw_DBO zx9Rt9`qB3Q*6sA;3-$`W^F#Pb9Ub_q^>!O!&+D-*vR?*K3I2}yMYpHka(@?b1uvG+ zA1|(N_0;H~{=P<;47NdG`3`|7jBN9}H>a&~YRlY?*~Jfa`SNszwG-pDle#(Zs40j< zyNq_&X_saE3hg!C?}G1Hc<+HccK=590NZKYuJAeV>&ur!zn{E!v|j%uZt`f|9w(14 ztzCv3)NgxIaq_(R+LZpVJ}SO^z5Xjc{pL@J{uFwG-ZIBXd606Ub5bF5Qs_@>1L55H zp(Ef65ZL#qzdUUO)41i5K(+Jwb2j zd+%Udq0nb-3H01fs&nAQ&Uup(9j82!`4oB$pu4TUm@sK0nap#& z*T4aD4!j2v<248v1PlTO0fT@+z#w1{FbEg~3<3rLgMdN6AYc$M2p9w$1bCFuKkn#6 z8IM80AYc$M2p9wm0tNwtfI+|@U=T0}7z7Lg1_6VBLBJqj5XeFx-gx4zv~E1LLhm`F zMd%fevhH!$dXL-!&ViTjT=3lsgy4G^eBXla`te;NzSjr++q718Bkd1{?_PMHvE3^4 zTGp_&u=bU*?=jq|dcAz+)Z)HV!8&|f4afURXkZ z{_X{Og5HuROFj10yXfyHt|4?5ir&`Bdiy&hjPLUM;`<5K+i)rmTkZD~q9^Fh{<_v1 z^r=;#zR{)cC2+an#dPaYxs82|?~*X|2CfK~zQwTWuk`I#&0iboFOH(xN$z9N&xC#V z(%-*Vf}Wr^^p~i28ta-S%UZh9#l4ckD^&PHby|{+;gb?v8rO&VIK;i>^(nnwLUqSI z$8V7}ly*NDN>t$z=}cXs=U-HP(|WUM2hbgyXNhIwgttTw>=Nh+dP82IPlP`!H%f2l z-(c4T(+3+bcz<&Z+aF}_R~?pC)|=X|TIjJ~^$ndba{2dNVS89#9kE~a_;-I*H}aw9 zdY0aCypnU|`7;yO9(`op{s%tZ!$R+xcFMAQhP5TWGVTr9U(&sv{@qbje^ZGgi9bm^ z4-*~5rbd&j>xh2|@o@MFk~^Ga9jN(JkNsf(hL^6nZpBXzdbpnXA8k1(k$P#z-mZI( z@1->K?)2h{#M6&lQFr_3$2kpk7tDWT*@gQqOsq-1(L-raY2s8o{*&9V}{gZ_&UY<0u z@%|ScTDkARuQW6bSftXx>0p_B6^qBP7djOlKYeDG#F(=>oc!!C?5@N^e}3J`&(-U1 zUY5DPqCS|P{qFB*AQ=rh6{Y^S;$CXsSMY z!YW3>9LIace>(eB^EQ8<#(vf5Zx_2?^$90dPH3IkJ#$t`Ti*NIJgo`rH|6Rj+IO<- zOMUW)R<-}xQgPRf(&3DZf7(sC_p9b~M16}M{dCX1(~=JCTb!0~Hm`rbW6*(bDe@EG zUpUau2RiU27s|fV0Y1wbOK)XvIzb1%dBO*INbkadem>BFuf1C13whwXXMlgdYS4l2 zR^fv@mv5|Z-)Yc+FC%=A=kncG&hM6N4^+}k(1CA*@IfB<77n~mjYfeFbl^jIf;{k@ z64{A ziXZggUn=~Ni+rPg1k(?C@UIho$VI-R_(2bT$cJ2{JB*+A=|sPPd9ieZzkfjfgXI9_ z3eWrD02<$xd9iz`MdAIbKeBG3HYt3p%s%l6y&s&o>2Jt9NV9e!H?GV2Ttp9p9E?9D zr-#T(UEZYSKHoqt4ZC094d;F22BC<*U-d`UUW7)j{i=cAb%Y(`7rZpL9zE3lAjOs$ zhTfnj=*^aL0DbD*@&45Jt#)%t;T8Kn<%VmvnP)Y3&+MEv{mkaByv#&!tiw^+7>^@c>I47YxN#r4J&h6!H=C-kJ1EB} zw#sTA*UQ~+<0me%JDymV52bc-t~M1_wUC3c)7~4f8OF%D#QGXF2_$% z8AkgZR*p5dPLJ2G?_~eA50-L#f^O%tDK?KgPC1tJq8!_Yg!CJpBr_kE;Fiu=-EH%_ zr#E+<>xunzysy%{7Vo7voPKaieX@gx%2Q}8*!W6n8k9c|s6vx4#Y!c&Xn z^U6I)@VJF;G9K)DuQ=_Km!AC&9+H0tkK+Z8h;jlv&g`7kHvO!w&bhPa1V!fzHxggv zQHAq)h3+AE@IA&uUsTcM3hAy873n&7Nd6r>rU)K_Q&0f#nB6(2ZFvmn>C>q{8vV_c(Y+{vAA~3Lb(}P$KX+w^Q|gvzxoy3o0PT zD89xT`(*zH}DJTVaw9cF}yQ8_FqM<~cIJ52i*_~b8 zmE(&PKvJH|g9p9d6nr^&Nd6r>q+hfJr=VcqG4q@`ogL@3bxohy-8`oyNEIEPIE$F5 z%6x6+thRH>!fGj~bZNPd<-w!aaYAJ`O8$Wda$*Zk2*U*)Epz8|cb+?ac30=@IfZn( zO^UB_GV!%_bGH&MC7V z$RU^U;Bg6zLttDY*{H`QFkXT22#k+Jjg#TM`hM!{YN&zd6Bs_Su2Jakb4f$7%V_Fz<&I6sR>p^$_3f>3$>^FvA-mvGJv!8sy&-iFi3=TPW#wBnCT>_@mU ze!;81k4r#L&>Qj(ed_QfO_uf5)riyMN$XZ|_&xf4L_a<&1Z@t+k8pkn!iXnQ&!zQt z8YW2bS zA!O%-o*zO}u@;`&NEp+9>p=NkC+T7QS5RAvFrSUXG(6YCm!16YecqaHSzpvaD|5M? zcjX`#Q~QHTb)GIKfaN1hUKLJW;nJ)4v<|Z^;t$J8ODDcO5ML1p>%Pi%=m!Sk2L-}| z)fs~>z3q$V)tzDK_n!OC@#(W)*Lno~()I7ZN%-)k_$!zD;&qJvtKt{E@1sXNw=F7O zDk`!hyDBmsCDwk3%(*Bwt($~1z#sD_&Q<2m!1iF^6GF; z0H2>M^WkGZ<&RHKdeR^N^FaI~0sim1=XI**|4hfjE`c2ay9D#;uvakO6rA_LJPhXp z*U3~*c-)x#RX#uGl=9)x=jSYv^K-;a&d~Nq^4!ww639XSX19mQt8UV1R`Vs6RlnzW zUl1eS=nZ;;-qPo2 zy+NNkpEN&U-M7lkGtU=X^pqRU?Zf=Q+k|n*#X74Go}cp$ouBg#(MQ>nT-VTE4G58| zHHKDRKea#U4SIs!(C$K?I>+semUZQ77jq6Dq4efGKj%jw_%Y8|VSJac4!MGQqjLlg zx85t~U$ov>4$I|!CQNUdTc4k!{korJzOc(aNyhQS4Wro{?s0un<4lsy;5buM8Ydpp zaMT2z*y--WpwVuYAc!ButRDs|Y!XHM9_6Ow_`o|q}lAB0_fI+|@U=T0}7z7Lg1_6VBLBJqj5HJWB z1PlTO0fT@+U@J$Uu<=CwtpY=)m!-C&@knE$0?|>i#-v{A)AMCq^@078h z8tA`H3o`E>;C=_h`#?{k?|?WyY%Q#PhOEDa+bQ1N_BKc}vqI z^aedaZ^>@0H|SI6i@qO8y|CKNqx(Hcob!bG;(HRVZ{MZgCi|Y`WNFXDb@RG;`B-o2 zdlE@!-0w+FoH*g6k>iX1pkz~gPjae!PjWX^ApV|&-BK@Q9kuu)V7o-Ij4vAuYT0}ZN*~xMfV%r=c3;Y z`!1@#f6oRzL2tkm`b7A%a>HyNP7C^bZhykQ1DfRd_Q&i0tn!iXx%LMCIX&EF!%hl* z2c*vF5&9R2j;rw=WB4nU#j^c*{6YU8u>o>)2Zr9U??|C~S9 z`_AdP>aySZ&guE$Lr;gE)3g8OsYXgez}NB{Nw6h4ZX2v@l!k2 z9lk-%>3QqY)#vT}X5;yH?X>!`|691?f6|vWjcHl8>X9)!H9bdtSX22UYetJzSx~8Pb9d>xNI8+K z)8pM=#7#JO;kq%U_}sLyludq4kA-u3N=ajX;5Fy;G`CcrSv|VBZPcjN>eiaW4jb80 zJ!))AYirxs>N5{*X=@$RHe>YYvC~IPA6;ENkA4TAJ-ejSST?&-v(=x|bJB6NX$3Vn z>C^T8eD|pqC%&FeI_{*-u8!9D3=x$6Hcu1b9N#dO$<>#?hy9$w;)D0PS|*Rf&+Xq* ziAoJ#5lV5XssiOVIPMg}^ z+}hSvd2DBETX$DmA$ui=RC*H&zZQny&Ux29AawxmFQ!w)iJDeaqM{yR57Ic=+iEu> z`<}sNzC!Sedd{bHpY{Jd>tFKqP0>H{hjiG<`o~TpTyd?~`FA_A-^Ka3x!tqpb{AU9 z6n&-Uh3rDyCPMo^h~eL~VchF?e?Ea<`T{+kmb@rz9J`PwfcEAl%i`bm^vjTqSmoG> zpxB&UjMo5{i$u>seC(0;jyTz)=c#kMW;C}HQL6=vQu%>tg*BcuU1r($T&n6f*X*gC zE$6g#>kN@SJ^b=@TAqVZPeYC$_UDUWH(5^N%x17TV2+S(Tcqxtxsk5xzNNbl+aATldwf{rr zDK6G-I^}m=32}XFzij#KDsVyl%m_X}AzkmUpG}<|ov{wQfq;NpDnG=PqkjG%*shlL z1pCUp-_dq&-?ppBN1-m)Pu|ZK>AXz(L)hNzvR#e#7y5*L@jU1~eWYK%Q^^*dbyjyf z=n8d9<#(Sa?eFu`0{!NZ9i7eY9?&j*Jm0!2wha9uo!=7u>fFiu((vwy&@bAtpnidd zo%HLs)b_Phex!@-qK!M1Z?Sd}@=>VEdaEHO*i{$%^y^B)dkp$p=oxlXxsbBFdX^{e z%e#<2tmPVL@xH}jF(N47G)}RsYTAt1e&8YX{{2csIsrbQw53b>VE+RXX7|1SiS0-j-&m4~IA>o0zm^~z4q)I+AG#&`&5vcq(Kb)Dw% z(v<3FiNR;#9%SpMy6M;V`x3wG(u%a`v~E85AzeYta35}1Ja9FxLBJqj5Xg-{nYBF= zB=)C2d{!}E+3lod@wo|Kqu-1fGiVOxS@llfZ@ZZ@?v+aH9znWl>BEVz=X=Oif9nlX zdZZ8Y+$C?69L{D`oL@rx&@dv!kGv{9u&J)UXuS_F#?UKShk38zTtCgh_F0+|4}0T9 z^3#7OKX|65*8Q5lFXot3LaW-@-#D@3OBeSZwtUq%b`K`kzD>?m(So+}zvyp+ZZ<5e zpK7`d{C-8sk!nSE9evd8_w93}4AdvKeQ7b3555p@S&qGYpSCNDu$SrJyXLb>82XH~ zm+#bxE%vXe zSwrXG=j~(R_mGGe_A>B`vX@_4JX>^ApSX6_+-Q6G(PHi8#*WT2trCWp>EJ)QP=>uZ zy~`UY+^_O&UuNuOT`y6VigS&`ULLU@!Z|mt_t&F>>TcO2-*uA6tQNuCZl|16vmC zW!M{G_Od$@t?(f*vfX_4a@yF-x)7d%350dwFh`Me8v}WhXM; z9c3!JWyxh)?0Spwsk)f?w$4{yt|!P&oL7gN)A%x{)LTb`euP2i=A$q1^R%A=rTbjI zVb)^^EXFYi7zDNw1UAR@7{RaoeX8);z7*rw%RVX!WViR4;?uU5`(!oHy^#a^zY&wppmo?{jD(VrS$R)3H=aqkX<3k<5dn7qQ+%i(1z ztei#PGxl;cHu3N+u=E;ogMdL`D@MR$FAvvNl*i6=a2Z6tsPFysIs=E)=UIPzO~|)+ zx$Wg$eG;+)w4UL=#s1~C(zTa^eY+!4f{Jf zUuHc)SRM7=L)in+2y55i=f#6D@`i){uz28VT!Vl?z#xzh0p1;N^V=W89V5+3zt8sN zv}65pkkVr>`=a{VUZ#in)-U(PdJNbbVfM0{S?(|R%65bHa&SFH+Stn)ItRaC-wRAV zWaNdt4E&<(<=E>n{!+BP+||}Rrxb%Z(q8_dKg)%NRGG|NWyY6t+je2)E&HAsU(Uv) zFkA~QzJ}f)U=Y}P5#Vl7zV{oXt*9_NGxvIoRLB@|E<|&WFDnZ^nw|SwuN~;v%fWPe z!a}cwe%khOUyLuq-Uzdo2RhhsU&2?m8?={$>oGFMUe?e#_=WY$9uo1wUIuA7>cg@V8Sjp=mpygJ;acMOit?y3nZBm)$CtBH=hfln^t~FV z)LTb`euP2i=EICHyI5#_d&5D0Hh!AN{51#|1PlWC5g2IpU(OFw42oeygCBYOe0&-9 zMwq?qCYSpQzOvn*y&N20w!d%IFKg_8U$E~5rY;rxU@rr|D0?~f`0{N<+sj?e=kxv; zoBq6#d;M81G^EO8^18mam$PksuMUm9oJ(F5D3~~dfI+|@;6=dQ zAHy1875Tkixb5J5ir=4md^x+H^Kpv}=-hM0mz_J}iIVeak1u0A2KHQzxBqf*e>t5g zw#WFq64)DI_OiQ{1$xPLgZ46yFCQ%XFL&|&%f?>z6sKUni?D}8ys(#nUzEKZdwlr^ zrP#}rbcl7=?Cey=x)Zq`7`bgbl(F2dS&xw$pZpj{mQxd95HJWB z1Of=eTaUqW{88WgQB=@|4LlslvzPH)-B&QL!pY}`*~{MZO47z&c0rFEv+|IL7xpsnE7@LtuvmL} zLPztQ?wKu>B+}!r^9=X{)HZr%B?z4mG<}l|j_&wmKFutsE z0J~M&%er01`F?1}J>e$0=lLlSS$|+J!`|pCdpTq5We@gRchH&ZdPu|zdl~qZY%eb@ z+FtIW&;7b8lg(YN*~yG^M-|^-onpoZ;&4aPsJ0?~ld+fGauij*^4~Z1a(;|*;~ZU3 zO^iXnAYc#(AV6JWDzPu!956tSI)?R;L3{a?kN!<-bW;hq0hxJ%x$R~Bd{~=VqJp-0 zFzhgd<%1(XD|@-H^%zbzl*c|r+fA^SVQ+-l%Wl58FX1cO)tbh+fvH6Bdq4Yjvwm4) z2mHeNWtRdz*vr7LSbLe}tR5L<)?A)vu_)J&=blu(h8r(N>wPl z`Sg%Pc$2qiyVqWz-OO#;P5*M)yKl~?^#Agex7p1+uif+u+D-miyY_Fj3-Ku5kc;vi zeI$ac#EXhA;Q%oTgT!|5^?BjDA!*Po3J>t`t427X+=vs-G&@SH~~<)g3knf}6U zs=Q^Vcx$`^{DW>b7SJc~i>pu6^S;t&d&NygpN_hMdPLYEa6Hf_@QbTYwAaP!(@8?8 zr+xVpuAPkp7& zg@L4QFP@vaMf0>8NWgdN;h`m8egbd^+ueGB~J>J#rXeWg#^=(8k!0>8NW z#CvI9>2uv7r<(TG(P*%pMc5&5JZNu$Up{>{PO+?N8u+kRl{oJ>xpU^MZYLRqc+~50 z_B*m={iqNr*|chGFa3Qp?-)IPfpV1JHS>=7G0Kf|b^$ea3<3rLgFplVG;+LI&O4Tu zhjrGTb$OB>)&GX&Eou&Ci=21-dSKpB>c9O@83VcCp5q2^>At<@*kt<*X$RTlBuE=Nc+%rm|s^Ng=)H}iXmU#nd_g!8TTIS{!h-d@GgX^#Ebd~{Nm~}E&Xm^>9c*#LkGNN z*6oOvygKyyqxA{=;_5Rg_ETT!Gt+JK>1xZXL$BYZfX}I)f?r&H+F}Ryl|GluHTr~( z{O>gJ^a=dp>J#rXeWlOz1xBBx=o9$G)n{7XOZ!Tn_Ju~DrRWp*<sF&rsV{&e;A9TIN`1HKv>pEX%-pt#s7w$Ls6^@y|UoEBx8ypHJexgs*Hj-@Iem%sXo69Q?xi zWejSCE@|FT^u8(P9o6RYl1`LO9h7-Tl~8X!g*bBv&=L8RlCVICH`;P#UoI@As6L)lg~SzUt`vr0`wy0HPV7#zV|-p6Xm1N z^tpVj(Pt_86#U}q6ZO2$^!bVTp2|^YG4)gMi>ptx*Tw78O>LO3-Hfw&VDa{`UcZM# zyxe~B_vOGZu0Cz)cl%18X`@e%vb;L<`aL88eFDF@`pk&^)K~gUUS!6>U2S=F==Hl4 z@S%PJzqtBLiyhoo`mB270J9DYN-CoN1b%V#iT9bl(&v&tn{{=LI*ZUJ@QbTYTi#3i zN}m~{Pgk8q=o9$m)2B1<_**?L@d}N{V64oOfJkrSlnHvD)v4WGo#(Vg(&dOyLoH#? z{BaJZ7*TrO@hzP%GjHbYrwjKR{0hg+%sa-YrG~^HU=RpHfVxC8?-&M5A@_z6F@E5~ z+|DMMcRWqo7Z}G+i@gE67~Yc}J*`+^9a;Ln2<*56?RSKemfYns*evZ;E+G z-YXdwmlKpvN^N7&-#f0?<zT`%*D@5nskdos`XzIHQzm-v5Z7wJOzPKsQV z?@c}LxTJeWGfxH33oPF}4i5bCz4t+%C?9>L&&&!Tt2bRL@32twJUtE2rrQhuC(=S!ML;sfhFP}c0dB@35s{M@$pLaZRW=Dr7sfByhFpE3Z;tKeQ>n+Bo=N8an23#uU>74l{7m?@j+hhrab1mXj`JPwFy}i0bB&+3UxweMfDiMIw&2Hhv0IiM{PXU! z>e$O)FU4N2Z0KrhM$!s(Bkkpf3YFxiSM@ddcVjO{mn)R7{I0Q=^JA17XMf=|A%lQH zz#xzV0qW6H+D6TD9(olCnK5HV;<;y^9fxz!;pUJZ5*2MPGqJY!%IFGV-CEBj_=dJG zU@ybo=qr0UY3yZB;fv~%JtX3Vy$t+{wU=4WT9Rpt-my-P>z;lTrz!g?liI^{6%vhV zG}uFqd!AcXG3OH4|B!Wg|I}`JgLac2%DTLdWL@6JvM%ov?I!;%@z$&AymX`kC^tJ=|5eC7T(?hzqtCu`%GWyv&!hxRc8_Q5b%quPg~wg z`%0flqtBA`3HIZ?y!!^fcsLa@RuoZg&258#L13##fV;&~*XdcIb0E>sM$bF)I=yY8899cZCC}rw z(&Bm0I*tg=rFg==^nD8J^i+D3!9nQ?+aH86_paNca8vFd=g_h+j-M2J19ma;%Fo1n z6F);Sg}C|F>7~uQqlQlXWgNqP9uo1ge$=@Hn`)ijtfKAZj^^&}wpoWXbtq`&He|{L9$O@$9*%vZwDGdpS2g`7tiM02>a2fI(nuMSw>mQ;Dy6vX8M!&n=7h zu4Nj0*Wzu5Fuv=h&+X4WzC18D^A>9_GiE%d%oqYcPq?7*W!M{iWiQ(c&3E8#F^uYy zT?+VMF9W}l?d3~~wU;N(nn5GXZL}mqxrLj~k@oUq$ZT=0vX|2vjlGOEpcL2G%TaYR z?)~BlvEecZ7zDOP1UA3%Wp_L-R3BTYy=)~$jvPs8KO>>-`pRBT8hhDO z_@eq=4~ckTF9W}l?d7YAx0lbUoJ?z%i@ub-9QN+~)1pNxMrAK2%XGesy%$xs;@vm+ z#ltE3oustFY`6^q27#>#0qPP{i6bb>`Suz8boWh))Pd@6J+Z;C6BX9ibL6M6ep#hK z864ybTfdC8%Z$B@HwVU-l?dmLeYzfxV|y%38H2qMW-q(>=DvilY&Y-vWn(XE=p6jQ z`ehG^cwsN61;1kLWtOv+WJ2$S?wgdIGVi+fuvp7Fz~=kje1_9`@7fjG?#&F)ZhDY} z%k+Lo=?d*82WrdPudUfvgXQRRT8BVu>AD3_UdkIaSJogLK?yOMXaJc2k{q_Q7rC8mTXML&SPv;V| z=Z*&uuRgtg4~ckLx9aRl!H;!|KFpW;e9$NGi>uF! zwB5z)6DbIH+s&Q<9$=uqpz9$KucJ@FFRnh(2ltge(?*{jWd-$!u!kg|Pv93*dq z^cQqJBmsQ_zqtBL%R6dc>C^tFIh)>_IJ7z7Lg27yon zXr$51L53nzz|CPqiyzo9e!EHLAg2fBAjRH*T}(<;7e5nz-6!yE?o<43zB$N@nS<1j zIk<)O%N`Q(vR%x3C;>mVi#66v;OHUmS%)lVEpgbQ_k44ZdOax58MxZ#Cweb89p1aH z{{WtVD0B{TTbXm*PP^$Hw42;s<{WpFImex3&T$v*CU=wgJ+zBdaK3qt-4?kh-vt*OgFb;@TzzK5mg+No zeq!_q9Tn4mRtbJ_^_do%xUclNqpjQLt&?7VHY%u}z%Q;o@ov*s`fML~ zlhLQ6F0T%~euu#EK%c-bu0CyfN9`+p+JlTf9VHdC>5mT%^Y+3ZH|V)OD!9M(&Z%u7`%(w@2?>S^+czXB_6F=?%sjC+-8lj7OZdum^UXop?`eBR z^Kb2cqx$4*T=+eQ=OBR}+r{qOpQDGobC8a`d|%P_^31c^=^Phpbao=+-BG48%9WSp zac`h-zbcdVE;?UjIp$0Y7wvMCmAkdTz3bJZWxcY~Gxdnm)Q)~Aji6-;_*2x@ObX1c zxp7{)!u)s!+^BST>f;R(%8!`j2?T*t49xkD0R(Z_qs`F*WM`7y~=NkNq!_BS7!QyGc1_6VBK_C(V zG96Qi$rNq&*^9&|Zv<>*c5x|#g94l68y9PtTGs-58TLk)y-W&~3-(vG8?=|#Zk*qH z;Pj18usfuA;}dCPF9Sq!qxxhIiFjcz1HUMH`K86P9eerORdciKWtOv+WZI(lsBc_e z*=ZulNhRL-X0Lij%QfDZXWqst<{Ovv?%M86?x|gSsCF}Z$~P@T<(rnhE%B=fy6k1q& z#rgz(arKFM-dFlu^5_A7H|uht(8Bcz{Nm~p?RD|`L|Vh$v{}dL0j6+$0>8NWOiRDp zXZjp$*5$eiEkd7yUtE1A#eV8DeQs;?S&}{lzqtCe#SZQ(eXe`N*h8i06Zpl|C*EiJ zN}p9-JDTr&9fcO&-U7e4`b^7vX>na#hG^$y<^@HPsCn&2*Y)Ck2|hA(DjD;zEs5dUg^(kyEnOycJ2Kn zJWS>p_m_Fb;WE$oMeQc5B>pSfMS?I-1-U5Sn|j`H$p$m;2+Vc4j9N6?rb@BRiQyb>1nq$UIU0lN2 zTG$3I75ljTROFq`-$}va6{jGN%P5j>ZHk~`q9E?N5F+30CiPOX- z{vAgA_(7Ead&hc8gZ}CLK!V}mejvfHmWpxwjMy8ni;*9GCZ4PN2Ls zzMmfKjWB!J%}=(Stm9(rr)TVC7sgOq8Q6Nr$P0Tpna5s^y`SEzMcd1BJGy87fA+ou z+^H)2K2oEiV#kiyVg-9_Z~;qHRP3=+H7W`!XzWh~jAh`7Ew&MRbR5S58tc3EsHj** zV+Y&BI*w(Gjx+w(O3uzb*-1FOr}&%sn|$BN-fORY_T8u4d(TU9?i)AeAyywFVFXS`QwhRmv^5q z>WI+`7Hvold1f_7X5jMg^hnX@Ne*YjH>mrJb#+`E_27z{muVpK~7b8 zFz`G|Id}OzhO9U0t(Sw}obsN)SFLpY9wXOWFPFQn(tmP)wWZ}^R9P=e|20}KyPiK? z`8`I@^8Ww!|9*KW{%|PIJ9nJ}>S0)PB9WUT%M%RrmWZ zo6ODH%^qm>!0)ODu&ituuqv9|d~Q<5$DN-mOOYt01qXnvm$_D!^|I*f`}+UiP@_vG4sk@d3lUq{!=j57z}W!&Yt zNzc!kRr9}H>@4Q>{k+Ua+uznZ^xUL%%kw0*ep!Y$EX&;b<~d0ln&%|-HP1=fxGZy< z7=E*|lsx3`!IX(B^ZVC+Zc^^9=5uzW&#Tvu_FNAR5?GT|K@i*<$B%m z@vP0owiKGr39!1u9z$EVT#Q;7&-r{#K;`~v?z;DpW_jXmOX~H9(af*<0<_& zzvpMnte+Otct%ccj;D-KNA91}fAc$@VY3ciP~(}IzHRe4JCy;o&q-UaI8+olKc)ZX zcRc0qnFTeTg&UjWSsA2`tcOhh&F^@o%-^L8YCI#iHplaqjHmRUYdkC8JFfT(zIPmX zw5e3X8*On&#Ko+9ht(-I?Wzv z_Q3D72k@zI%YYTo_~!SH9iIWKqpB2%BA>_qD&ISHR^L0C^@gmAF^HuXk12ZjzCbhY zDb>>Ty<@ETy<@q{D*aaPzHGS|m4CPLxk=K0To;%7nhuq5nE(IRV#Zy6?|9`EE0{4g z2R33}-#Z5LqPmWt4t?*~&wTH=iTU1fGlRD<-!n$d_l#Sa?-{o#%h+~?A5fN(L*;W* z6IbT