From f1229c5401494b7d809817fa43e4d25076451341 Mon Sep 17 00:00:00 2001 From: talamh Date: Sun, 2 May 2021 01:58:40 +0000 Subject: [PATCH 001/111] Added spawn egg for killer rabbitt --- .../mobs_mc_spawn_icon_rabbit_caerbannog.png | Bin 0 -> 1897 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit_caerbannog.png diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit_caerbannog.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit_caerbannog.png new file mode 100644 index 0000000000000000000000000000000000000000..4244a83c6f0a93ff1f7d65180fd6d56b43e98af3 GIT binary patch literal 1897 zcmV-v2bTDWP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1YulI182{O1&N1WN)Wj>8%;H<;s3VuS0|@?KYW zmmM}(W=UmAvR(i0-{Jnj!5qBvK`o{j4;()E#2Fnst|Om!I{bNG56AAjv%C8R!z5_s zdbGIg9d^ceUiP}y$*_lqg;HNH%KI02EyT7q*gLL`gsu&awXn-;A>p;Nzn;tG))ABG zqYHJ7AM5=|11>jjUX){qq#k$AhiXjd8y{Z5Tbn>d&;9R>K0doWl!1x6kQ}(%L@4tj z$!NoQXN;M)EV3+%3aG{IQ1sL0_4V-zx!cf}BD1U*2UO;c{F~ZCB17#+Av|IV<8+T;Z@u_B<0# zLrPT0*$`v}XQf0883%c4lxa{u+e#G>J$F{L%oXBR2ctoZ#1(Rq_<7P`l_X6JVpoKN zz{)okI=4;dc9jepH!_FlAS_0h@>i$(&Y&@7LJ=Kya|K*HBO55DazySR41*#x7OCMR zc%L7SsjEQ2aMEmWFdt>E0QpOxx8RafXu-gM_R1sDwiW#G=JYD!H<&Qhg0IR;^Z3&5fHhx|g6?PQug-im@jMu2TUL$2>JVjJ)Tm z+|=wyJc}R$WSHVKnu?=QtWgX4k#5C0k&@74l-_&0nZM zRQI^rPS^%yVYyRXk>0&FnxL&&4|}Qy>|;&%M(f@gq=T{5_4$b}k9f+$Q^fUg6gfFW zwnkcjn(r*hu3^nfr|$=3&&w&UqcpzM%N~COS(kRf29#~Q5b+2nBlzMqa#wEwL6vJu zVOnjpH5$}!kABV3%@vBpcD{GJweaa8&Lki4GFFpb^0iQDDnknAwvg&Gp4;Au#saK$ zVRvs%JZob+HwYC`f`Yv^%X+@Xe@ySw=uRtWJO_kc(nu|(a&K7EHNmR(bT6(=*FuFA z)h?R*NagX8(x*|^U1*EeEPd=GfD?Mjr#XWL{Qch$%Y_QXTw6&y?#y+B!{VT8uKx1G zr}D|)J2Jk={o|7Vc}|~F@duZ6QWxPwxUB)L%JgzDt?zz{YW5HG@r4cmQA9RD<3UIBDK7$1w-QnX|n=&!S6J#FSNeT0%D6YqIUEif*S>-oYH>emR5}^Fkwg@_oh35b$_S93CGmdz$@Es=#J; zeN9ja714I3q6@tu+)BDBeyF5T)-tFLe)~f-Vq8coja2Q-F895(dJZ}6uSk_y2F|BM z2ufQ4noTQziPQIMt^tazs0rq%XIq2V_qc*JAdmcS!E-OmM6aK8ekfIob4^iObE(#y zUHC(`UzN+Jt^3o7f4Y$32Qj(-0gvB171uc!#sB~S24YJ`L;%PDS^!tH0(VpZ000Sa zNLh0L01FcU01FcV0GgZ_00007bV*G`2jv9<0V4$`wT`m@000?uMObu0Z*6U5Zgc=c za%Ew3Wn>_CX>@2HM@dakSAh-}0004CNklbF5XOHoK`b;JVIM$K99Z8z zgPq_DXerpKg^gMWSBOs`_yF2S;;Kp&{r>lkCK@B4V3=Z)r$1%5iFTC>(}10W(?Yt0g{KT~|LB0{1RiBgp!Ypopv*h^Cyz`N@%B3xU*m=o zt`rm4%`%KJzZ1nVec%Xe6THe6MC2Pa2#BJHEhpZv%>xfW)2*`v&{}%{_i;?3R4HDb z=M{hjU}YMGL~8(+ouB79BEnr9^9gJkL&Mt2MOG*rgJ*!3k+ECA8*mx~W9K~f7fu|v j9Vl0|3LH#0`#-TSNF9Mg)SuCN00000NkvXXu0mjfBRps$ literal 0 HcmV?d00001 From e6b61a1551948352bf7e3dce3f59f7238a5d413e Mon Sep 17 00:00:00 2001 From: talamh Date: Sun, 2 May 2021 02:00:21 +0000 Subject: [PATCH 002/111] Update 'mods/ENTITIES/mobs_mc/rabbit.lua' --- mods/ENTITIES/mobs_mc/rabbit.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 90d5c27bf..2a9521ecb 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -233,4 +233,4 @@ mobs:spawn(spawn_grass) mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) -- Note: This spawn egg does not exist in Minecraft -mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit.png^[colorize:#FF0000:192", 0) -- TODO: Update inventory image +mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit_caerbannog.png", 0) From e9f38c6b90ea33234a75a1a95dc03b94c760f602 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 22 May 2021 10:47:28 +0200 Subject: [PATCH 003/111] WIP raycast base buckets --- mods/ITEMS/mcl_buckets/init.lua | 320 +++++++++++++++++++++----------- 1 file changed, 211 insertions(+), 109 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 7e67eee8e..3103aeb4f 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -44,129 +44,166 @@ local place_liquid = function(pos, itemstring) sound_place(itemstring, pos) minetest.add_node(pos, {name=itemstring, param2=fullness}) end +local function give_bucket(new_bucket, itemstack, user) + if itemstack:get_count() == 1 then + return new_bucket + else + local inv = user:get_inventory() + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) + else + minetest.add_item(user:get_pos(), new_bucket) + end + if not minetest.is_creative_enabled(user:get_player_name()) then + itemstack:take_item() + end + return itemstack + end +end + +local function bucket_raycast(user) + local pos = user:get_pos() + pos.y = pos.y + user:get_properties().eye_height + local look_dir = user:get_look_dir() + look_dir = vector.multiply(look_dir, 6) + local pos2 = vector.add(pos, look_dir) + + local ray = raycast(pos, pos2, false, true) + if ray then + for pointed_thing in ray do + if pointed_thing and get_node_group(get_node(pointed_thing.above).name, "_mcl_bucket_pointable") == 1 then + --minetest.chat_send_all("found!") + return {under=pointed_thing.under,above=pointed_thing.above} + end + end + end + return nil +end function mcl_buckets.register_liquid(def) - for i=1, #def.source_take do - mcl_buckets.liquids[def.source_take[i]] = { + for _,source in ipairs(def.source_take) do + mcl_buckets.liquids[source] = { source_place = def.source_place, - source_take = def.source_take[i], + source_take = source, on_take = def.on_take, itemname = def.itemname, } if type(def.source_place) == "string" then - mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[def.source_take[i]] + mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[source] end end - if def.itemname ~= nil then - minetest.register_craftitem(def.itemname, { - description = def.name, - _doc_items_longdesc = def.longdesc, - _doc_items_usagehelp = def.usagehelp, - _tt_help = def.tt_help, - inventory_image = def.inventory_image, - stack_max = 1, - groups = def.groups, - on_place = function(itemstack, user, pointed_thing) - -- Must be pointing to node - if pointed_thing.type ~= "node" then - return - end + if def.itemname == nil or def.itemname == "" then + error(string.format("[mcl_bucket] Invalid itemname then registering [%s]!", def.name)) + end - local node = minetest.get_node(pointed_thing.under) - local place_pos = pointed_thing.under - local nn = node.name - -- Call on_rightclick if the pointed node defines it - if user and not user:get_player_control().sneak then - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then - return minetest.registered_nodes[nn].on_rightclick(place_pos, node, user, itemstack) or itemstack - end - end + minetest.register_craftitem(def.itemname, { + description = def.name, + _doc_items_longdesc = def.longdesc, + _doc_items_usagehelp = def.usagehelp, + _tt_help = def.tt_help, + inventory_image = def.inventory_image, + stack_max = 1, + groups = def.groups, + on_place = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end - local node_place - if type(def.source_place) == "function" then - node_place = def.source_place(place_pos) - else - node_place = def.source_place + local node = minetest.get_node(pointed_thing.under) + local place_pos = pointed_thing.under + local nn = node.name + -- Call on_rightclick if the pointed node defines it + if user and not user:get_player_control().sneak then + if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then + return minetest.registered_nodes[nn].on_rightclick(place_pos, node, user, itemstack) or itemstack end - -- Check if pointing to a buildable node - local item = itemstack:get_name() + end - if def.extra_check and def.extra_check(place_pos, user) == false then - -- Fail placement of liquid - elseif minetest.registered_nodes[nn] and minetest.registered_nodes[nn].buildable_to then - -- buildable; replace the node - local pns = user:get_player_name() - if minetest.is_protected(place_pos, pns) then - minetest.record_protection_violation(place_pos, pns) + local node_place + if type(def.source_place) == "function" then + node_place = def.source_place(place_pos) + else + node_place = def.source_place + end + -- Check if pointing to a buildable node + local item = itemstack:get_name() + + if def.extra_check and def.extra_check(place_pos, user) == false then + -- Fail placement of liquid + elseif minetest.registered_nodes[nn] and minetest.registered_nodes[nn].buildable_to then + -- buildable; replace the node + local pns = user:get_player_name() + if minetest.is_protected(place_pos, pns) then + minetest.record_protection_violation(place_pos, pns) + return itemstack + end + place_liquid(place_pos, node_place) + if mod_doc and doc.entry_exists("nodes", node_place) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) + end + else + -- not buildable to; place the liquid above + -- check if the node above can be replaced + local abovenode = minetest.get_node(pointed_thing.above) + if minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to then + local pn = user:get_player_name() + if minetest.is_protected(pointed_thing.above, pn) then + minetest.record_protection_violation(pointed_thing.above, pn) return itemstack end - place_liquid(place_pos, node_place) + place_liquid(pointed_thing.above, node_place) if mod_doc and doc.entry_exists("nodes", node_place) then doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) end else - -- not buildable to; place the liquid above - -- check if the node above can be replaced - local abovenode = minetest.get_node(pointed_thing.above) - if minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to then - local pn = user:get_player_name() - if minetest.is_protected(pointed_thing.above, pn) then - minetest.record_protection_violation(pointed_thing.above, pn) - return itemstack - end - place_liquid(pointed_thing.above, node_place) - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end - else - -- do not remove the bucket with the liquid - return - end - end - - -- Handle bucket item and inventory stuff - if not minetest.is_creative_enabled(user:get_player_name()) then - -- Add empty bucket and put it into inventory, if possible. - -- Drop empty bucket otherwise. - local new_bucket = ItemStack("mcl_buckets:bucket_empty") - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) - else - minetest.add_item(user:get_pos(), new_bucket) - end - itemstack:take_item() - return itemstack - end - else + -- do not remove the bucket with the liquid return end - end, - _on_dispense = function(stack, pos, droppos, dropnode, dropdir) - local iname = stack:get_name() - local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" + end - if def.extra_check and def.extra_check(droppos, nil) == false then - -- Fail placement of liquid - elseif buildable then - -- buildable; replace the node - local node_place - if type(def.source_place) == "function" then - node_place = def.source_place(droppos) + -- Handle bucket item and inventory stuff + if not minetest.is_creative_enabled(user:get_player_name()) then + -- Add empty bucket and put it into inventory, if possible. + -- Drop empty bucket otherwise. + local new_bucket = ItemStack("mcl_buckets:bucket_empty") + if itemstack:get_count() == 1 then + return new_bucket + else + local inv = user:get_inventory() + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) else - node_place = def.source_place + minetest.add_item(user:get_pos(), new_bucket) end - place_liquid(droppos, node_place) - stack:set_name("mcl_buckets:bucket_empty") + itemstack:take_item() + return itemstack end - return stack - end, - }) - end + else + return + end + end, + _on_dispense = function(stack, pos, droppos, dropnode, dropdir) + local iname = stack:get_name() + local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" + + if def.extra_check and def.extra_check(droppos, nil) == false then + -- Fail placement of liquid + elseif buildable then + -- buildable; replace the node + local node_place + if type(def.source_place) == "function" then + node_place = def.source_place(droppos) + else + node_place = def.source_place + end + place_liquid(droppos, node_place) + stack:set_name("mcl_buckets:bucket_empty") + end + return stack + end, + }) end minetest.register_craftitem("mcl_buckets:bucket_empty", { @@ -174,26 +211,25 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { _doc_items_longdesc = S("A bucket can be used to collect and release liquids."), _doc_items_usagehelp = S("Punch a liquid source to collect it. You can then use the filled bucket to place the liquid somewhere else."), _tt_help = S("Collects liquids"), - - liquids_pointable = true, + --liquids_pointable = true, inventory_image = "bucket.png", stack_max = 16, on_place = function(itemstack, user, pointed_thing) - -- Must be pointing to node + --[[-- Must be pointing to node if pointed_thing.type ~= "node" then return itemstack end -- Call on_rightclick if the pointed node defines it - local node = minetest.get_node(pointed_thing.under) - local nn = node.name - if user and not user:get_player_control().sneak then - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then - return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack - end - end + + + local pointed_liquid = bucket_raycast(user) -- Can't steal liquids + if minetest.is_protected(pointed_liquid.above, user:get_player_name()) then + minetest.record_protection_violation(pointed_liquid.under, user:get_player_name()) + return itemstack + end if minetest.is_protected(pointed_thing.above, user:get_player_name()) then minetest.record_protection_violation(pointed_thing.under, user:get_player_name()) return itemstack @@ -208,8 +244,8 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { if not minetest.is_creative_enabled(user:get_player_name()) then new_bucket = ItemStack({name = liquiddef.itemname}) if liquiddef.on_take then - liquiddef.on_take(user) - end + liquiddef.on_take(user) + end end minetest.add_node(pointed_thing.under, {name="air"}) @@ -252,7 +288,73 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { end return itemstack end + end]] + if pointed_thing.type ~= "node" then + return itemstack end + local node = minetest.get_node(pointed_thing.under) + local nn = node.name + if user and not user:get_player_control().sneak then + if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then + return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack + end + end + + local liquid_node = bucket_raycast(user) + if liquid_node then + if minetest.is_protected(liquid_node.above, user:get_player_name()) then + minetest.record_protection_violation(liquid_node.above, user:get_player_name()) + end + local liquid_name = get_node(liquid_node.above).name + if liquid_name then + local liquid_def = mcl_buckets.liquids[liquid_name] + if liquid_def then + local new_bucket + --minetest.chat_send_all("test") + -- Fill bucket, but not in Creative Mode + -- FIXME: remove this line + --if not minetest.is_creative_enabled(user:get_player_name()) then + if not false then + new_bucket = ItemStack({name = liquid_def.itemname}) + if liquid_def.on_take then + liquid_def.on_take(user) + end + end + add_node(liquid_node.above, {name="air"}) + sound_take(nn, liquid_node.above) + + if mod_doc and doc.entry_exists("nodes", liquid_name) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", liquid_name) + end + if new_bucket then + return give_bucket(new_bucket, itemstack, user) + end + else + minetest.log("error", string.format("[mcl_buckets] Node [%s] has invalid group [_mcl_bucket_pointable]!", liquid_name)) + end + end + return itemstack + else + -- FIXME: replace this ugly code by cauldrons API + if nn == "mcl_cauldrons:cauldron_3" then + -- Take water out of full cauldron + minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + if not minetest.is_creative_enabled(user:get_player_name()) then + new_bucket = ItemStack("mcl_buckets:bucket_water") + end + sound_take("mcl_core:water_source", pointed_thing.under) + elseif nn == "mcl_cauldrons:cauldron_3r" then + -- Take river water out of full cauldron + minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + if not minetest.is_creative_enabled(user:get_player_name()) then + new_bucket = ItemStack("mcl_buckets:bucket_river_water") + end + sound_take("mclx_core:river_water_source", pointed_thing.under) + end + if new_bucket then + return give_bucket(new_bucket, itemstack, user) + end + end end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) -- Fill empty bucket with liquid or drop bucket if no liquid From 5d65c8a3aa58da596befac454eae5ed205e2e510 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 22 May 2021 18:57:51 +0200 Subject: [PATCH 004/111] Working empty bucket --- mods/ITEMS/mcl_buckets/init.lua | 6 ++++++ mods/ITEMS/mcl_core/nodes_liquid.lua | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 3103aeb4f..327d553c8 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -11,6 +11,11 @@ local mod_doc = minetest.get_modpath("doc") local mod_mcl_core = minetest.get_modpath("mcl_core") local mod_mclx_core = minetest.get_modpath("mclx_core") +local raycast = minetest.raycast +local get_node = minetest.get_node +local add_node = minetest.add_node +local get_node_group = minetest.get_node_group + if mod_mcl_core then minetest.register_craft({ output = 'mcl_buckets:bucket_empty 1', @@ -355,6 +360,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { return give_bucket(new_bucket, itemstack, user) end end + return itemstack end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) -- Fill empty bucket with liquid or drop bucket if no liquid diff --git a/mods/ITEMS/mcl_core/nodes_liquid.lua b/mods/ITEMS/mcl_core/nodes_liquid.lua index c49b685eb..47c22c7c6 100644 --- a/mods/ITEMS/mcl_core/nodes_liquid.lua +++ b/mods/ITEMS/mcl_core/nodes_liquid.lua @@ -100,7 +100,7 @@ S("• When water is directly below lava, the water turns into stone."), liquid_range = 7, post_effect_color = {a=209, r=0x03, g=0x3C, b=0x5C}, stack_max = 64, - groups = { water=3, liquid=3, puts_out_fire=1, freezes=1, not_in_creative_inventory=1, dig_by_piston=1}, + groups = { water=3, liquid=3, puts_out_fire=1, freezes=1, not_in_creative_inventory=1, dig_by_piston=1, _mcl_bucket_pointable=1}, _mcl_blast_resistance = 100, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode _mcl_hardness = -1, @@ -203,7 +203,7 @@ S("• When lava is directly above water, the water turns into stone."), _mcl_node_death_message = lava_death_messages, post_effect_color = {a=245, r=208, g=73, b=10}, stack_max = 64, - groups = { lava=3, lava_source=1, liquid=2, destroys_items=1, not_in_creative_inventory=1, dig_by_piston=1, set_on_fire=15, fire_damage=1}, + groups = { lava=3, lava_source=1, liquid=2, destroys_items=1, not_in_creative_inventory=1, dig_by_piston=1, set_on_fire=15, fire_damage=1, _mcl_bucket_pointable=1}, _mcl_blast_resistance = 100, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode _mcl_hardness = -1, From 17202115fa2e99fb825dcaf53c73bbaf9a47cb82 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 22 May 2021 18:58:58 +0200 Subject: [PATCH 005/111] cache general functions --- mods/ITEMS/mcl_buckets/init.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 327d553c8..7f5ab2b16 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -11,6 +11,10 @@ local mod_doc = minetest.get_modpath("doc") local mod_mcl_core = minetest.get_modpath("mcl_core") local mod_mclx_core = minetest.get_modpath("mclx_core") +local vector = vector +local math = math +local string = string + local raycast = minetest.raycast local get_node = minetest.get_node local add_node = minetest.add_node From 640b0dc4859014f15939cce0be36dd06c2b1419c Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 2 Jun 2021 00:23:11 +0200 Subject: [PATCH 006/111] basic title API working (testing needed) --- mods/HUD/mcl_title/init.lua | 161 ++++++++++++++++++++++++++++++++++++ mods/HUD/mcl_title/mod.conf | 4 + 2 files changed, 165 insertions(+) create mode 100644 mods/HUD/mcl_title/init.lua create mode 100644 mods/HUD/mcl_title/mod.conf diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua new file mode 100644 index 000000000..9975ff840 --- /dev/null +++ b/mods/HUD/mcl_title/init.lua @@ -0,0 +1,161 @@ +--TODO: use SSCSM to reduce lag and network trafic (just send modchannel messages) +--TODO: exactly mc like layout + +local huds_idx = {} + +huds_idx.title = {} +huds_idx.subtitle = {} +huds_idx.actionbar = {} + +mcl_title = {} +mcl_title.defaults = {fadein = 10, stay = 70, fadeout = 20} +mcl_title.layout = {} +mcl_title.layout.title = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = -1.3}, size = 5} +mcl_title.layout.subtitle = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = 1.9}, size = 2} +mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = -15}, size = 1} + +local get_color = mcl_util.get_color + +local function gametick_to_secondes(gametick) + return gametick / 20 +end + + +--PARAMS SYSTEM +local player_params = {} + +minetest.register_on_joinplayer(function(player) + player_params[player] = { + stay = gametick_to_secondes(mcl_title.defaults.stay), + --fadeIn = gametick_to_secondes(mcl_title.defaults.fadein), + --fadeOut = gametick_to_secondes(mcl_title.defaults.fadeout), + } +end) + +minetest.register_on_leaveplayer(function(player) + player_params = nil +end) + +function mcl_title.params_set(player, data) + player_params[player] = { + stay = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.defaults.stay), + --fadeIn = gametick_to_secondes(data.fadeIn) or gametick_to_secondes(mcl_title.defaults.fadein), + --fadeOut = gametick_to_secondes(data.fadeOut) or gametick_to_secondes(mcl_title.defaults.fadeout), + } +end + +function mcl_title.params_get(player) + return player_params[player] +end + +--API FUNCTIONS + +function mcl_title.set(player, type, data) + if not data.color then + data.color = "white" + end + local _, hex_color = get_color(data.color) + if not hex_color then + return false + end + + if huds_idx[type][player] then + player:hud_remove(huds_idx[type][player]) + end + + --TODO: enable this code then Fleckenstein's pr get merged + --[[ + local bold + if data.bold == "true" then + bold = true + else + bold = false + end + + local italic + if data.italic == "true" then + italic = true + else + italic = false + end]] + + local stay = mcl_title.params_get(player).stay + + huds_idx[type][player] = player:hud_add({ + hud_elem_type = "text", + position = mcl_title.layout[type].position, + alignment = mcl_title.layout[type].alignment, + text = data.text, + --bold = bold, + --italic = italic, + size = {x = mcl_title.layout[type].size}, + number = hex_color, + z_index = 1100, + }) + + minetest.after(stay, function() + if huds_idx[type][player] then + player:hud_remove(huds_idx[type][player]) + end + huds_idx[type][player] = nil + end) + return true +end + +function mcl_title.remove(player, type) + if huds_idx[type][player] then + player:hud_remove(huds_idx[type][player]) + end + huds_idx[type][player] = nil +end + +function mcl_title.clear(player) + mcl_title.remove(player, "title") + mcl_title.remove(player, "subtitle") + mcl_title.remove(player, "actionbar") +end + +minetest.register_on_dieplayer(function(player) + mcl_title.clear(player) +end) + + +--TEMP STUFF!! +--TODO: remove then testing/tweaking done +minetest.register_chatcommand("title", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.set(player, "title", {text=param, color="gold"}) + end, +}) + +minetest.register_chatcommand("subtitle", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.set(player, "subtitle", {text=param, color="gold"}) + end, +}) + +minetest.register_chatcommand("actionbar", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.set(player, "actionbar", {text=param, color="gold"}) + end, +}) + +minetest.register_chatcommand("timeout", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.params_set(player, {stay = 600}) + end, +}) + +minetest.register_chatcommand("all", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.params_set(player, {stay = 600}) + mcl_title.set(player, "title", {text=param, color="gold"}) + mcl_title.set(player, "subtitle", {text=param, color="gold"}) + mcl_title.set(player, "actionbar", {text=param, color="gold"}) + end, +}) \ No newline at end of file diff --git a/mods/HUD/mcl_title/mod.conf b/mods/HUD/mcl_title/mod.conf new file mode 100644 index 000000000..0f29a8118 --- /dev/null +++ b/mods/HUD/mcl_title/mod.conf @@ -0,0 +1,4 @@ +name = mcl_title +description = Add an API to add in HUD title +depends = mcl_colors +author = AFCMS \ No newline at end of file From 6b53dda79bf8b31309206ea29b6e84184cc17fc7 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 2 Jun 2021 00:25:15 +0200 Subject: [PATCH 007/111] add todo list --- mods/HUD/mcl_title/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 9975ff840..41b4dfc4a 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -1,4 +1,5 @@ --TODO: use SSCSM to reduce lag and network trafic (just send modchannel messages) +--TODO: fadeIn and fadeOut animation (needs engine change: SSCSM or native support) --TODO: exactly mc like layout local huds_idx = {} From c8102838cb80e5ada8649a7ccf48c1c288a4de2b Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 2 Jun 2021 00:26:10 +0200 Subject: [PATCH 008/111] add missing TODO entry (bold+italic) --- mods/HUD/mcl_title/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 41b4dfc4a..807ed19c9 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -65,6 +65,7 @@ function mcl_title.set(player, type, data) end --TODO: enable this code then Fleckenstein's pr get merged + --TODO: be sure API is correctly used --[[ local bold if data.bold == "true" then From 7e64470f7086c2978f0ad48710d6c0f253b6c3cb Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 2 Jun 2021 11:07:31 +0200 Subject: [PATCH 009/111] fix future API usage of bold+italic pr --- mods/HUD/mcl_title/init.lua | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 807ed19c9..83277b3bf 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -64,22 +64,10 @@ function mcl_title.set(player, type, data) player:hud_remove(huds_idx[type][player]) end - --TODO: enable this code then Fleckenstein's pr get merged - --TODO: be sure API is correctly used - --[[ - local bold - if data.bold == "true" then - bold = true - else - bold = false - end + --TODO: enable this code then Fleckenstein's pr get merged (in about 5-6 years) - local italic - if data.italic == "true" then - italic = true - else - italic = false - end]] + --if data.bold == nil then data.bold = false end + --if data.italic == nil then data.italic = false end local stay = mcl_title.params_get(player).stay @@ -88,8 +76,8 @@ function mcl_title.set(player, type, data) position = mcl_title.layout[type].position, alignment = mcl_title.layout[type].alignment, text = data.text, - --bold = bold, - --italic = italic, + --bold = data.bold, + --italic = data.italic, size = {x = mcl_title.layout[type].size}, number = hex_color, z_index = 1100, From b9fd1ac227c59407a92ca208d1fd71681c7952f0 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 2 Jun 2021 11:12:15 +0200 Subject: [PATCH 010/111] credit digminecraft for the tutorial --- mods/HUD/mcl_title/init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 83277b3bf..a2fd82b24 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -1,3 +1,5 @@ +--Based on https://www.digminecraft.com/game_commands/title_command.php + --TODO: use SSCSM to reduce lag and network trafic (just send modchannel messages) --TODO: fadeIn and fadeOut animation (needs engine change: SSCSM or native support) --TODO: exactly mc like layout From 2603c4768ba34be059b8f3dd175985bc08683cea Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 7 Jun 2021 22:32:05 +0200 Subject: [PATCH 011/111] mcl_title: basic mc like layout (collide with other mods) --- mods/HUD/mcl_title/init.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index a2fd82b24..ffd740b4a 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -1,7 +1,11 @@ ---Based on https://www.digminecraft.com/game_commands/title_command.php +--Based on: +--https://www.digminecraft.com/game_commands/title_command.php +--https://youtu.be/oVrtQRO2hpY --TODO: use SSCSM to reduce lag and network trafic (just send modchannel messages) --TODO: fadeIn and fadeOut animation (needs engine change: SSCSM or native support) +--TODO: allow obfuscating text (needs engine change: SSCSM or native support) +--TODO: allow colorizing and styling of part of the text (NEEDS ENGINE CHANGE!!!) --TODO: exactly mc like layout local huds_idx = {} @@ -13,9 +17,9 @@ huds_idx.actionbar = {} mcl_title = {} mcl_title.defaults = {fadein = 10, stay = 70, fadeout = 20} mcl_title.layout = {} -mcl_title.layout.title = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = -1.3}, size = 5} -mcl_title.layout.subtitle = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = 1.9}, size = 2} -mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = -15}, size = 1} +mcl_title.layout.title = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = -1.3}, size = 7} +mcl_title.layout.subtitle = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = 1.7}, size = 4} +mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = -11}, size = 2} local get_color = mcl_util.get_color From 40f4287ff200ec20bb2d25650a0b37606bd74b38 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 12 Jun 2021 12:21:01 +0200 Subject: [PATCH 012/111] new buckets fixes --- mods/ITEMS/mcl_buckets/init.lua | 50 ++++++++++++++++------------ mods/ITEMS/mcl_buckets/register.lua | 2 +- mods/ITEMS/mcl_core/nodes_liquid.lua | 4 +-- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 23d7244e5..f2f61ccfc 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -18,7 +18,8 @@ local string = string local raycast = minetest.raycast local get_node = minetest.get_node local add_node = minetest.add_node -local get_node_group = minetest.get_node_group +local add_item = minetest.add_item + if mod_mcl_core then minetest.register_craft({ @@ -26,7 +27,7 @@ if mod_mcl_core then recipe = { {"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"}, {"", "mcl_core:iron_ingot", ""}, - } + }, }) end @@ -34,42 +35,47 @@ mcl_buckets = {} mcl_buckets.liquids = {} -- Sound helper functions for placing and taking liquids -local sound_place = function(itemname, pos) +local function sound_place(itemname, pos) local def = minetest.registered_nodes[itemname] if def and def.sounds and def.sounds.place then minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true) end end -local sound_take = function(itemname, pos) +local function sound_take(itemname, pos) local def = minetest.registered_nodes[itemname] if def and def.sounds and def.sounds.dug then minetest.sound_play(def.sounds.dug, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true) end end -local place_liquid = function(pos, itemstring) +local function place_liquid(pos, itemstring) local fullness = minetest.registered_nodes[itemstring].liquid_range sound_place(itemstring, pos) minetest.add_node(pos, {name=itemstring, param2=fullness}) end local function give_bucket(new_bucket, itemstack, user) - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) - else - minetest.add_item(user:get_pos(), new_bucket) - end - if not minetest.is_creative_enabled(user:get_player_name()) then - itemstack:take_item() - end + local inv = user:get_inventory() + if minetest.is_creative_enabled(user:get_player_name()) then + --TODO: is a full bucket added if inv doesn't contain one? return itemstack + else + if itemstack:get_count() == 1 then + return new_bucket + else + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) + else + add_item(user:get_pos(), new_bucket) + end + itemstack:take_item() + return itemstack + end end end +local pointable_sources = {} + local function bucket_raycast(user) local pos = user:get_pos() pos.y = pos.y + user:get_properties().eye_height @@ -77,10 +83,10 @@ local function bucket_raycast(user) look_dir = vector.multiply(look_dir, 6) local pos2 = vector.add(pos, look_dir) - local ray = raycast(pos, pos2, false, true) + local ray = raycast(pos, pos2, false, true) if ray then for pointed_thing in ray do - if pointed_thing and get_node_group(get_node(pointed_thing.above).name, "_mcl_bucket_pointable") == 1 then + if pointed_thing and pointable_sources[get_node(pointed_thing.above).name] then --minetest.chat_send_all("found!") return {under=pointed_thing.under,above=pointed_thing.above} end @@ -97,6 +103,7 @@ function mcl_buckets.register_liquid(def) on_take = def.on_take, itemname = def.itemname, } + pointable_sources[source] = true if type(def.source_place) == "string" then mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[source] end @@ -137,7 +144,7 @@ function mcl_buckets.register_liquid(def) node_place = def.source_place end -- Check if pointing to a buildable node - local item = itemstack:get_name() + --local item = itemstack:get_name() if def.extra_check and def.extra_check(place_pos, user) == false then -- Fail placement of liquid @@ -308,7 +315,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack end end - + local new_bucket local liquid_node = bucket_raycast(user) if liquid_node then if minetest.is_protected(liquid_node.above, user:get_player_name()) then @@ -318,7 +325,6 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { if liquid_name then local liquid_def = mcl_buckets.liquids[liquid_name] if liquid_def then - local new_bucket --minetest.chat_send_all("test") -- Fill bucket, but not in Creative Mode -- FIXME: remove this line diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index 863aa074c..12790598c 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -3,7 +3,7 @@ local mod_mcl_core = minetest.get_modpath("mcl_core") local mod_mclx_core = minetest.get_modpath("mclx_core") local has_awards = minetest.get_modpath("awards") -local sound_place = function(itemname, pos) +local function sound_place(itemname, pos) local def = minetest.registered_nodes[itemname] if def and def.sounds and def.sounds.place then minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true) diff --git a/mods/ITEMS/mcl_core/nodes_liquid.lua b/mods/ITEMS/mcl_core/nodes_liquid.lua index d4234b8ac..0e0f71a11 100644 --- a/mods/ITEMS/mcl_core/nodes_liquid.lua +++ b/mods/ITEMS/mcl_core/nodes_liquid.lua @@ -95,7 +95,7 @@ S("• When water is directly below lava, the water turns into stone."), liquid_range = 7, post_effect_color = {a=209, r=0x03, g=0x3C, b=0x5C}, stack_max = 64, - groups = { water=3, liquid=3, puts_out_fire=1, freezes=1, not_in_creative_inventory=1, dig_by_piston=1, _mcl_bucket_pointable=1}, + groups = { water=3, liquid=3, puts_out_fire=1, freezes=1, not_in_creative_inventory=1, dig_by_piston=1}, _mcl_blast_resistance = 100, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode _mcl_hardness = -1, @@ -196,7 +196,7 @@ S("• When lava is directly above water, the water turns into stone."), damage_per_second = 4*2, post_effect_color = {a=245, r=208, g=73, b=10}, stack_max = 64, - groups = { lava=3, lava_source=1, liquid=2, destroys_items=1, not_in_creative_inventory=1, dig_by_piston=1, set_on_fire=15, fire_damage=1, _mcl_bucket_pointable=1}, + groups = { lava=3, lava_source=1, liquid=2, destroys_items=1, not_in_creative_inventory=1, dig_by_piston=1, set_on_fire=15, fire_damage=1}, _mcl_blast_resistance = 100, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode _mcl_hardness = -1, From 30e2e0d70afbbadf9fc7181bfde097ccf6fdd014 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 14 Jun 2021 14:36:17 +0200 Subject: [PATCH 013/111] test values --- mods/ITEMS/mcl_buckets/init.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index f2f61ccfc..70a219ffb 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -77,10 +77,11 @@ end local pointable_sources = {} local function bucket_raycast(user) - local pos = user:get_pos() + --local pos = user:get_pos() + local pos = mcl_util.get_object_center(user) pos.y = pos.y + user:get_properties().eye_height local look_dir = user:get_look_dir() - look_dir = vector.multiply(look_dir, 6) + look_dir = vector.multiply(look_dir, 4) local pos2 = vector.add(pos, look_dir) local ray = raycast(pos, pos2, false, true) From 8e931e92f57ce18792a846828e0e942f52f8eef1 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Fri, 9 Jul 2021 11:34:23 +0200 Subject: [PATCH 014/111] refactor mcl_title to be more efficient --- mods/HUD/mcl_title/init.lua | 120 +++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 30 deletions(-) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index ffd740b4a..48c3a909f 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -8,8 +8,17 @@ --TODO: allow colorizing and styling of part of the text (NEEDS ENGINE CHANGE!!!) --TODO: exactly mc like layout +--Note that the table storing timeouts use playername as index insteed of player objects (faster) +--This is intended in order to speedup the process of removing HUD elements the the timeout is up + local huds_idx = {} +local hud_hide_timeouts = {} + +hud_hide_timeouts.title = {} +hud_hide_timeouts.subtitle = {} +hud_hide_timeouts.actionbar = {} + huds_idx.title = {} huds_idx.subtitle = {} huds_idx.actionbar = {} @@ -19,10 +28,13 @@ mcl_title.defaults = {fadein = 10, stay = 70, fadeout = 20} mcl_title.layout = {} mcl_title.layout.title = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = -1.3}, size = 7} mcl_title.layout.subtitle = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = 1.7}, size = 4} -mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = -11}, size = 2} +mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = 0}, size = 1} local get_color = mcl_util.get_color +local string = string +local pairs = pairs + local function gametick_to_secondes(gametick) return gametick / 20 end @@ -32,15 +44,64 @@ end local player_params = {} minetest.register_on_joinplayer(function(player) - player_params[player] = { + local playername = player:get_player_name() + player_params[playername] = { stay = gametick_to_secondes(mcl_title.defaults.stay), --fadeIn = gametick_to_secondes(mcl_title.defaults.fadein), --fadeOut = gametick_to_secondes(mcl_title.defaults.fadeout), - } + } + local _, hex_color = get_color("white") + huds_idx.title[player] = player:hud_add({ + hud_elem_type = "text", + position = mcl_title.layout.title.position, + alignment = mcl_title.layout.title.alignment, + text = "", + --bold = data.bold, + --italic = data.italic, + size = {x = mcl_title.layout.title.size}, + number = hex_color, + z_index = 100, + }) + huds_idx.subtitle[player] = player:hud_add({ + hud_elem_type = "text", + position = mcl_title.layout.subtitle.position, + alignment = mcl_title.layout.subtitle.alignment, + text = "", + --bold = data.bold, + --italic = data.italic, + size = {x = mcl_title.layout.subtitle.size}, + number = hex_color, + z_index = 100, + }) + huds_idx.actionbar[player] = player:hud_add({ + hud_elem_type = "text", + position = mcl_title.layout.actionbar.position, + offset = {x = 0, y = -210}, + alignment = mcl_title.layout.actionbar.alignment, + --bold = data.bold, + --italic = data.italic, + text = "", + size = {x = mcl_title.layout.actionbar.size}, + number = hex_color, + z_index = 100, + }) end) minetest.register_on_leaveplayer(function(player) - player_params = nil + local playername = player:get_player_name() + + --remove player params from the list + player_params[player] = nil + + --remove HUD idx from the list (HUD elements are removed by the engine) + huds_idx.title[player] = nil + huds_idx.subtitle[player] = nil + huds_idx.actionbar[player] = nil + + --remove timers form list + hud_hide_timeouts.title[playername] = nil + hud_hide_timeouts.subtitle[playername] = nil + hud_hide_timeouts.actionbar[playername] = nil end) function mcl_title.params_set(player, data) @@ -66,43 +127,22 @@ function mcl_title.set(player, type, data) return false end - if huds_idx[type][player] then - player:hud_remove(huds_idx[type][player]) - end - --TODO: enable this code then Fleckenstein's pr get merged (in about 5-6 years) --if data.bold == nil then data.bold = false end --if data.italic == nil then data.italic = false end - local stay = mcl_title.params_get(player).stay + player:hud_change(huds_idx[type][player], "text", data.text) + player:hud_change(huds_idx[type][player], "number", hex_color) - huds_idx[type][player] = player:hud_add({ - hud_elem_type = "text", - position = mcl_title.layout[type].position, - alignment = mcl_title.layout[type].alignment, - text = data.text, - --bold = data.bold, - --italic = data.italic, - size = {x = mcl_title.layout[type].size}, - number = hex_color, - z_index = 1100, - }) - - minetest.after(stay, function() - if huds_idx[type][player] then - player:hud_remove(huds_idx[type][player]) - end - huds_idx[type][player] = nil - end) + hud_hide_timeouts[type][player:get_player_name()] = data.stay or mcl_title.params_get(player).stay return true end function mcl_title.remove(player, type) - if huds_idx[type][player] then - player:hud_remove(huds_idx[type][player]) + if player then + player:hud_change(huds_idx[type][player], "text", "") end - huds_idx[type][player] = nil end function mcl_title.clear(player) @@ -115,6 +155,26 @@ minetest.register_on_dieplayer(function(player) mcl_title.clear(player) end) +minetest.register_globalstep(function(dtime) + local new_timeouts = { + title = {}, + subtitle = {}, + actionbar = {}, + } + for element, content in pairs(hud_hide_timeouts) do + for name, timeout in pairs(content) do + timeout = timeout - dtime + if timeout <= 0 then + local player = minetest.get_player_by_name(name) + mcl_title.remove(player, element) + else + new_timeouts[element][name] = timeout + end + end + end + hud_hide_timeouts = new_timeouts +end) + --TEMP STUFF!! --TODO: remove then testing/tweaking done From d2f7d3136028f726d3aaba1ff7e4304e1952aef5 Mon Sep 17 00:00:00 2001 From: Emojigit Date: Sat, 10 Jul 2021 10:16:55 +0800 Subject: [PATCH 015/111] Fix warning in `mcl_end` This fixes: ``` 2021-07-10 10:00:58: WARNING[Main]: get_mapgen_params is deprecated; use get_mapgen_setting instead (at .../../games/MineClone2/mods/ITEMS/mcl_end/chorus_plant.lua:456) ``` --- mods/ITEMS/mcl_end/chorus_plant.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_end/chorus_plant.lua b/mods/ITEMS/mcl_end/chorus_plant.lua index 24307b5ed..4dc54db18 100644 --- a/mods/ITEMS/mcl_end/chorus_plant.lua +++ b/mods/ITEMS/mcl_end/chorus_plant.lua @@ -453,7 +453,7 @@ function mcl_end.grow_chorus_plant_step(pos, node, pr) end --- ABM --- -local seed = minetest.get_mapgen_params().seed +local seed = minetest.get_mapgen_setting("seed") local pr = PseudoRandom(seed) minetest.register_abm({ label = "Chorus plant growth", From 549bdeb6e9683e7b28048a56e36089d1e79c8f71 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 12 Jul 2021 21:41:57 +0000 Subject: [PATCH 016/111] Remove object:is_player --- mods/ITEMS/mcl_core/functions.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index 6e1a977d9..eceb81c51 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -203,7 +203,8 @@ minetest.register_abm({ chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) for _,object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then + local entity = object:get_luaentity() + if entity and entity.name == "__builtin:item" then object:remove() end end From d26b1b1402056b5add6bf25d5e791bfc6c8b1ab1 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 09:10:01 +0200 Subject: [PATCH 017/111] use mcl_util.call_on_rightclick insteed of current implementation --- mods/ITEMS/mcl_buckets/init.lua | 27 ++++++++++++++++----------- mods/ITEMS/mcl_buckets/mod.conf | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 70a219ffb..fdd08bdf9 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -3,6 +3,7 @@ local modname = minetest.get_current_modname() local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) +-- Compatibility with old bucket mod minetest.register_alias("bucket:bucket_empty", "mcl_buckets:bucket_empty") minetest.register_alias("bucket:bucket_water", "mcl_buckets:bucket_water") minetest.register_alias("bucket:bucket_lava", "mcl_buckets:bucket_lava") @@ -11,6 +12,7 @@ local mod_doc = minetest.get_modpath("doc") local mod_mcl_core = minetest.get_modpath("mcl_core") --local mod_mclx_core = minetest.get_modpath("mclx_core") +-- Localize some functions for faster access local vector = vector local math = math local string = string @@ -127,16 +129,15 @@ function mcl_buckets.register_liquid(def) if pointed_thing.type ~= "node" then return end + -- Call on_rightclick if the pointed node defines it + local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing) + if new_stack then + return new_stack + end local node = minetest.get_node(pointed_thing.under) local place_pos = pointed_thing.under local nn = node.name - -- Call on_rightclick if the pointed node defines it - if user and not user:get_player_control().sneak then - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then - return minetest.registered_nodes[nn].on_rightclick(place_pos, node, user, itemstack) or itemstack - end - end local node_place if type(def.source_place) == "function" then @@ -306,16 +307,20 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { return itemstack end end]] + -- Must be pointing to node if pointed_thing.type ~= "node" then return itemstack end + + -- Call on_rightclick if the pointed node defines it + local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing) + if new_stack then + return new_stack + end + local node = minetest.get_node(pointed_thing.under) local nn = node.name - if user and not user:get_player_control().sneak then - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then - return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack - end - end + local new_bucket local liquid_node = bucket_raycast(user) if liquid_node then diff --git a/mods/ITEMS/mcl_buckets/mod.conf b/mods/ITEMS/mcl_buckets/mod.conf index 5a78e70ad..0d7b764b8 100644 --- a/mods/ITEMS/mcl_buckets/mod.conf +++ b/mods/ITEMS/mcl_buckets/mod.conf @@ -1,6 +1,6 @@ name = mcl_buckets author = Kahrl description = -depends = mcl_worlds +depends = mcl_worlds, mcl_util optional_depends = mcl_core, mclx_core, doc From b0127fc1c3cb66ba0e024b9ea4cf82080ea80ced Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 09:18:15 +0200 Subject: [PATCH 018/111] fix bucket dispense function --- mods/ITEMS/mcl_buckets/init.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index fdd08bdf9..95ec97443 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -205,11 +205,16 @@ function mcl_buckets.register_liquid(def) _on_dispense = function(stack, pos, droppos, dropnode, dropdir) local iname = stack:get_name() local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" + if not buildable then return stack end - if def.extra_check and def.extra_check(droppos, nil) == false then - -- Fail placement of liquid - elseif buildable then - -- buildable; replace the node + local result + if def.extra_check then + result = def.extra_check(droppos, nil) + if result == nil then result = true end + else + result = true + end + if result then -- Fail placement of liquid if result is false local node_place if type(def.source_place) == "function" then node_place = def.source_place(droppos) From ca277b6769c8edb1c498c268dd349bd2cd6c72ee Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 11:29:15 +0200 Subject: [PATCH 019/111] mcl_bucket code refactoring + fix extra_check noot working --- mods/ITEMS/mcl_buckets/API.md | 30 +++++- mods/ITEMS/mcl_buckets/init.lua | 144 ++++++++++++++++++++++------ mods/ITEMS/mcl_buckets/register.lua | 26 +---- 3 files changed, 149 insertions(+), 51 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/API.md b/mods/ITEMS/mcl_buckets/API.md index 53f7d3698..4595d8e72 100644 --- a/mods/ITEMS/mcl_buckets/API.md +++ b/mods/ITEMS/mcl_buckets/API.md @@ -15,7 +15,33 @@ Accept folowing params: * 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. +* extra_check(pos, placer): (optional) function(pos) * 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 + +**Usage exemple:** +```lua +mcl_buckets.register_liquid({ + itemname = "dummy:bucket_dummy", + source_place = "dummy:dummy_source", + source_take = {"dummy:dummy_source"}, + inventory_image = "bucket_dummy.png", + name = S("Dummy liquid Bucket"), + longdesc = S("This bucket is filled with a dummy liquid."), + usagehelp = S("Place it to empty the bucket and create a dummy liquid source."), + tt_help = S("Places a dummy liquid source"), + extra_check = function(pos, placer) + --pos = pos where the liquid should be placed + --placer people who tried to place the bucket (can be nil) + + --no liquid node will be placed + --the bucket will not be emptied + --return false, false + + --liquid node will be placed + --the bucket will be emptied + return true, true + end, + groups = { dummy_group = 123 }, +}) +``` \ No newline at end of file diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 95ec97443..9ae712ced 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -56,6 +56,7 @@ local function place_liquid(pos, itemstring) sound_place(itemstring, pos) minetest.add_node(pos, {name=itemstring, param2=fullness}) end + local function give_bucket(new_bucket, itemstack, user) local inv = user:get_inventory() if minetest.is_creative_enabled(user:get_player_name()) then @@ -81,6 +82,7 @@ local pointable_sources = {} local function bucket_raycast(user) --local pos = user:get_pos() local pos = mcl_util.get_object_center(user) + --local pos = vector.add(user:get_pos(), user:get_bone_position("Head_Control")) pos.y = pos.y + user:get_properties().eye_height local look_dir = user:get_look_dir() look_dir = vector.multiply(look_dir, 4) @@ -98,6 +100,53 @@ local function bucket_raycast(user) return nil end +local function get_node_place(source_place, place_pos) + local node_place + if type(source_place) == "function" then + node_place = source_place(place_pos) + else + node_place = source_place + end + return node_place +end + +local function get_extra_check(check, pos, user) + local result + local take_bucket + if check then + result, take_bucket = check(pos, user) + if result == nil then result = true end + if take_bucket == nil then take_bucket = true end + else + result = true + take_bucket = true + end + return result, take_bucket +end + +local function get_bucket_drop(itemstack, user, take_bucket) + -- Handle bucket item and inventory stuff + if take_bucket and not minetest.is_creative_enabled(user:get_player_name()) then + -- Add empty bucket and put it into inventory, if possible. + -- Drop empty bucket otherwise. + local new_bucket = ItemStack("mcl_buckets:bucket_empty") + if itemstack:get_count() == 1 then + return new_bucket + else + local inv = user:get_inventory() + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) + else + add_item(user:get_pos(), new_bucket) + end + itemstack:take_item() + return itemstack + end + else + return itemstack + end +end + function mcl_buckets.register_liquid(def) for _,source in ipairs(def.source_take) do mcl_buckets.liquids[source] = { @@ -135,23 +184,75 @@ function mcl_buckets.register_liquid(def) return new_stack end - local node = minetest.get_node(pointed_thing.under) - local place_pos = pointed_thing.under - local nn = node.name + local undernode = get_node(pointed_thing.under) + local abovenode = get_node(pointed_thing.above) + local nn = undernode.name + local buildable1 = minetest.registered_nodes[undernode.name] and minetest.registered_nodes[undernode.name].buildable_to + local buildable2 = minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to + if not buildable1 and not buildable2 then return itemstack end --if both nodes aren't buildable_to, skip + + if buildable1 then + local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.under, user) + if result then + local node_place = get_node_place(def.source_place, pointed_thing.under) + local pns = user:get_player_name() - local node_place - if type(def.source_place) == "function" then - node_place = def.source_place(place_pos) + -- Check protection + if minetest.is_protected(pointed_thing.under, pns) then + minetest.record_protection_violation(pointed_thing.under, pns) + return itemstack + end + + -- Place liquid + place_liquid(pointed_thing.under, node_place) + + -- Update doc mod + if mod_doc and doc.entry_exists("nodes", node_place) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) + end + end + return get_bucket_drop(itemstack, user, take_bucket) + elseif buildable2 then + local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.above, user) + if result then + local node_place = get_node_place(def.source_place, pointed_thing.above) + local pns = user:get_player_name() + + -- Check protection + if minetest.is_protected(pointed_thing.above, pns) then + minetest.record_protection_violation(pointed_thing.above, pns) + return itemstack + end + + -- Place liquid + place_liquid(pointed_thing.above, node_place) + + -- Update doc mod + if mod_doc and doc.entry_exists("nodes", node_place) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) + end + end + return get_bucket_drop(itemstack, user, take_bucket) else - node_place = def.source_place + return itemstack end + -- Check if pointing to a buildable node --local item = itemstack:get_name() - if def.extra_check and def.extra_check(place_pos, user) == false then - -- Fail placement of liquid - elseif minetest.registered_nodes[nn] and minetest.registered_nodes[nn].buildable_to then - -- buildable; replace the node + --[[ + if buildable_to_1 then + if can_place(pos) then + Place + end + else if buildable_to_2 then + if can_place2() then + Place + end + end + ]] + --[[ + if result then -- Fail placement of liquid if result is false local pns = user:get_player_name() if minetest.is_protected(place_pos, pns) then minetest.record_protection_violation(place_pos, pns) @@ -200,28 +301,17 @@ function mcl_buckets.register_liquid(def) end else return - end + end]] end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) local iname = stack:get_name() local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" if not buildable then return stack end - - local result - if def.extra_check then - result = def.extra_check(droppos, nil) - if result == nil then result = true end - else - result = true - end + local result, take_bucket = get_extra_check(def.extra_check, droppos, nil) if result then -- Fail placement of liquid if result is false - local node_place - if type(def.source_place) == "function" then - node_place = def.source_place(droppos) - else - node_place = def.source_place - end - place_liquid(droppos, node_place) + place_liquid(droppos, get_node_place(def.source_place, droppos)) + end + if take_bucket then stack:set_name("mcl_buckets:bucket_empty") end return stack diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index 12790598c..97349533e 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -53,15 +53,6 @@ if mod_mcl_core then usagehelp = S("Place it to empty the bucket and create a water source."), tt_help = S("Places a water source"), extra_check = function(pos, placer) - -- Check protection - local placer_name = "" - if placer then - placer_name = placer:get_player_name() - end - if placer and minetest.is_protected(pos, placer_name) then - minetest.record_protection_violation(pos, placer_name) - return false - end local nn = minetest.get_node(pos).name -- Pour water into cauldron if minetest.get_item_group(nn, "cauldron") ~= 0 then @@ -70,13 +61,13 @@ if mod_mcl_core then minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3"}) end sound_place("mcl_core:water_source", pos) - return false + return false, true -- Evaporate water if used in Nether (except on cauldron) else local dim = mcl_worlds.pos_to_dimension(pos) if dim == "nether" then minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) - return false + return false, true end end end, @@ -96,15 +87,6 @@ if mod_mclx_core then usagehelp = S("Place it to empty the bucket and create a river water source."), tt_help = S("Places a river water source"), extra_check = function(pos, placer) - -- Check protection - local placer_name = "" - if placer then - placer_name = placer:get_player_name() - end - if placer and minetest.is_protected(pos, placer_name) then - minetest.record_protection_violation(pos, placer_name) - return false - end local nn = minetest.get_node(pos).name -- Pour into cauldron if minetest.get_item_group(nn, "cauldron") ~= 0 then @@ -113,13 +95,13 @@ if mod_mclx_core then minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3r"}) end sound_place("mcl_core:water_source", pos) - return false + return false, true else -- Evaporate water if used in Nether (except on cauldron) local dim = mcl_worlds.pos_to_dimension(pos) if dim == "nether" then minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) - return false + return false, true end end end, From cd08df175c767fe502065d5327d37ec633c7af2e Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 11:41:09 +0200 Subject: [PATCH 020/111] add better documentation --- mods/ITEMS/mcl_buckets/API.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_buckets/API.md b/mods/ITEMS/mcl_buckets/API.md index 4595d8e72..abbdb0a07 100644 --- a/mods/ITEMS/mcl_buckets/API.md +++ b/mods/ITEMS/mcl_buckets/API.md @@ -23,7 +23,14 @@ Accept folowing params: ```lua mcl_buckets.register_liquid({ itemname = "dummy:bucket_dummy", - source_place = "dummy:dummy_source", + --source_place = "dummy:dummy_source", + source_place = function(pos) + if condition then + return "dummy:dummy_source" + else + return "dummy:dummy_source_nether" + end + end, source_take = {"dummy:dummy_source"}, inventory_image = "bucket_dummy.png", name = S("Dummy liquid Bucket"), From 88e59d3592b7f56044273296bce96e299cf2de17 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 11:52:27 +0200 Subject: [PATCH 021/111] more mt like API (improved readability) --- mods/ITEMS/mcl_buckets/API.md | 14 +-- mods/ITEMS/mcl_buckets/init.lua | 150 +--------------------------- mods/ITEMS/mcl_buckets/register.lua | 9 +- 3 files changed, 14 insertions(+), 159 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/API.md b/mods/ITEMS/mcl_buckets/API.md index abbdb0a07..93af64acf 100644 --- a/mods/ITEMS/mcl_buckets/API.md +++ b/mods/ITEMS/mcl_buckets/API.md @@ -1,15 +1,18 @@ # mcl_buckets Add an API to register buckets to mcl -## mcl_buckets.register_liquid(def) +## mcl_buckets.register_liquid(itemname, def) + +Register a new bucket of liquid. + +`itemname` is the itemstring of the new bucket item + +`def` is a table containing the folowing fields: -Register a new liquid -Accept folowing params: * 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) @@ -21,8 +24,7 @@ Accept folowing params: **Usage exemple:** ```lua -mcl_buckets.register_liquid({ - itemname = "dummy:bucket_dummy", +mcl_buckets.register_liquid("dummy:bucket_dummy", { --source_place = "dummy:dummy_source", source_place = function(pos) if condition then diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 9ae712ced..11fede816 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -147,13 +147,13 @@ local function get_bucket_drop(itemstack, user, take_bucket) end end -function mcl_buckets.register_liquid(def) +function mcl_buckets.register_liquid(itemname, def) for _,source in ipairs(def.source_take) do mcl_buckets.liquids[source] = { source_place = def.source_place, source_take = source, on_take = def.on_take, - itemname = def.itemname, + itemname = itemname, } pointable_sources[source] = true if type(def.source_place) == "string" then @@ -161,11 +161,7 @@ function mcl_buckets.register_liquid(def) end end - if def.itemname == nil or def.itemname == "" then - error(string.format("[mcl_bucket] Invalid itemname then registering [%s]!", def.name)) - end - - minetest.register_craftitem(def.itemname, { + minetest.register_craftitem(itemname, { description = def.name, _doc_items_longdesc = def.longdesc, _doc_items_usagehelp = def.usagehelp, @@ -236,72 +232,6 @@ function mcl_buckets.register_liquid(def) else return itemstack end - - -- Check if pointing to a buildable node - --local item = itemstack:get_name() - - --[[ - if buildable_to_1 then - if can_place(pos) then - Place - end - else if buildable_to_2 then - if can_place2() then - Place - end - end - ]] - --[[ - if result then -- Fail placement of liquid if result is false - local pns = user:get_player_name() - if minetest.is_protected(place_pos, pns) then - minetest.record_protection_violation(place_pos, pns) - return itemstack - end - place_liquid(place_pos, node_place) - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end - else - -- not buildable to; place the liquid above - -- check if the node above can be replaced - local abovenode = minetest.get_node(pointed_thing.above) - if minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to then - local pn = user:get_player_name() - if minetest.is_protected(pointed_thing.above, pn) then - minetest.record_protection_violation(pointed_thing.above, pn) - return itemstack - end - place_liquid(pointed_thing.above, node_place) - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end - else - -- do not remove the bucket with the liquid - return - end - end - - -- Handle bucket item and inventory stuff - if not minetest.is_creative_enabled(user:get_player_name()) then - -- Add empty bucket and put it into inventory, if possible. - -- Drop empty bucket otherwise. - local new_bucket = ItemStack("mcl_buckets:bucket_empty") - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) - else - minetest.add_item(user:get_pos(), new_bucket) - end - itemstack:take_item() - return itemstack - end - else - return - end]] end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) local iname = stack:get_name() @@ -328,80 +258,6 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { inventory_image = "bucket.png", stack_max = 16, on_place = function(itemstack, user, pointed_thing) - --[[-- Must be pointing to node - if pointed_thing.type ~= "node" then - return itemstack - end - - -- Call on_rightclick if the pointed node defines it - - - local pointed_liquid = bucket_raycast(user) - - -- Can't steal liquids - if minetest.is_protected(pointed_liquid.above, user:get_player_name()) then - minetest.record_protection_violation(pointed_liquid.under, user:get_player_name()) - return itemstack - end - if minetest.is_protected(pointed_thing.above, user:get_player_name()) then - minetest.record_protection_violation(pointed_thing.under, user:get_player_name()) - return itemstack - end - - -- Check if pointing to a liquid source - local liquiddef = mcl_buckets.liquids[nn] - local new_bucket - if liquiddef and liquiddef.itemname and (nn == liquiddef.source_take) then - - -- 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.on_take then - liquiddef.on_take(user) - end - end - - minetest.add_node(pointed_thing.under, {name="air"}) - sound_take(nn, pointed_thing.under) - - if mod_doc and doc.entry_exists("nodes", nn) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn) - end - - elseif nn == "mcl_cauldrons:cauldron_3" then - -- Take water out of full cauldron - minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) - if not minetest.is_creative_enabled(user:get_player_name()) then - new_bucket = ItemStack("mcl_buckets:bucket_water") - end - sound_take("mcl_core:water_source", pointed_thing.under) - elseif nn == "mcl_cauldrons:cauldron_3r" then - -- Take river water out of full cauldron - minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) - if not minetest.is_creative_enabled(user:get_player_name()) then - new_bucket = ItemStack("mcl_buckets:bucket_river_water") - end - sound_take("mclx_core:river_water_source", pointed_thing.under) - end - - -- Add liquid bucket and put it into inventory, if possible. - -- Drop new bucket otherwise. - if new_bucket then - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) - else - minetest.add_item(user:get_pos(), new_bucket) - end - if not minetest.is_creative_enabled(user:get_player_name()) then - itemstack:take_item() - end - return itemstack - end - end]] -- Must be pointing to node if pointed_thing.type ~= "node" then return itemstack diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index 97349533e..46abce1d0 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -19,7 +19,7 @@ end]] if mod_mcl_core then -- Lava bucket - mcl_buckets.register_liquid({ + mcl_buckets.register_liquid("mcl_buckets:bucket_lava", { source_place = function(pos) local dim = mcl_worlds.pos_to_dimension(pos) if dim == "nether" then @@ -34,7 +34,6 @@ if mod_mcl_core then awards.unlock(user:get_player_name(), "mcl:hotStuff") end end, - itemname = "mcl_buckets:bucket_lava", inventory_image = "bucket_lava.png", name = S("Lava Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."), @@ -43,10 +42,9 @@ if mod_mcl_core then }) -- Water bucket - mcl_buckets.register_liquid({ + mcl_buckets.register_liquid("mcl_buckets:bucket_water", { source_place = "mcl_core:water_source", source_take = {"mcl_core:water_source"}, - itemname = "mcl_buckets:bucket_water", inventory_image = "bucket_water.png", name = S("Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with water."), @@ -77,10 +75,9 @@ end if mod_mclx_core then -- River water bucket - mcl_buckets.register_liquid({ + mcl_buckets.register_liquid("mcl_buckets:bucket_river_water", { source_place = "mclx_core:river_water_source", source_take = {"mclx_core:river_water_source"}, - itemname = "mcl_buckets:bucket_river_water", inventory_image = "bucket_river_water.png", name = S("River Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with river water."), From cf5703d528426bbbb810c327ecfe59b0c9867cf0 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 11:53:37 +0200 Subject: [PATCH 022/111] fix luacheck warnings --- mods/ITEMS/mcl_buckets/init.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 11fede816..a496fb2ff 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -182,11 +182,10 @@ function mcl_buckets.register_liquid(itemname, def) local undernode = get_node(pointed_thing.under) local abovenode = get_node(pointed_thing.above) - local nn = undernode.name local buildable1 = minetest.registered_nodes[undernode.name] and minetest.registered_nodes[undernode.name].buildable_to local buildable2 = minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to if not buildable1 and not buildable2 then return itemstack end --if both nodes aren't buildable_to, skip - + if buildable1 then local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.under, user) if result then @@ -234,7 +233,6 @@ function mcl_buckets.register_liquid(itemname, def) end end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) - local iname = stack:get_name() local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" if not buildable then return stack end local result, take_bucket = get_extra_check(def.extra_check, droppos, nil) From 6d7aafe0d462bccdb8a7a32f78a27898fb1705d7 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 15:13:40 +0200 Subject: [PATCH 023/111] Revert "more mt like API (improved readability)" This reverts commit 88e59d3592b7f56044273296bce96e299cf2de17. --- mods/ITEMS/mcl_buckets/API.md | 14 ++- mods/ITEMS/mcl_buckets/init.lua | 150 +++++++++++++++++++++++++++- mods/ITEMS/mcl_buckets/register.lua | 9 +- 3 files changed, 159 insertions(+), 14 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/API.md b/mods/ITEMS/mcl_buckets/API.md index 93af64acf..abbdb0a07 100644 --- a/mods/ITEMS/mcl_buckets/API.md +++ b/mods/ITEMS/mcl_buckets/API.md @@ -1,18 +1,15 @@ # mcl_buckets Add an API to register buckets to mcl -## mcl_buckets.register_liquid(itemname, def) - -Register a new bucket of liquid. - -`itemname` is the itemstring of the new bucket item - -`def` is a table containing the folowing fields: +## mcl_buckets.register_liquid(def) +Register a new liquid +Accept folowing params: * 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) @@ -24,7 +21,8 @@ Register a new bucket of liquid. **Usage exemple:** ```lua -mcl_buckets.register_liquid("dummy:bucket_dummy", { +mcl_buckets.register_liquid({ + itemname = "dummy:bucket_dummy", --source_place = "dummy:dummy_source", source_place = function(pos) if condition then diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index a496fb2ff..b75c10696 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -147,13 +147,13 @@ local function get_bucket_drop(itemstack, user, take_bucket) end end -function mcl_buckets.register_liquid(itemname, def) +function mcl_buckets.register_liquid(def) for _,source in ipairs(def.source_take) do mcl_buckets.liquids[source] = { source_place = def.source_place, source_take = source, on_take = def.on_take, - itemname = itemname, + itemname = def.itemname, } pointable_sources[source] = true if type(def.source_place) == "string" then @@ -161,7 +161,11 @@ function mcl_buckets.register_liquid(itemname, def) end end - minetest.register_craftitem(itemname, { + if def.itemname == nil or def.itemname == "" then + error(string.format("[mcl_bucket] Invalid itemname then registering [%s]!", def.name)) + end + + minetest.register_craftitem(def.itemname, { description = def.name, _doc_items_longdesc = def.longdesc, _doc_items_usagehelp = def.usagehelp, @@ -231,6 +235,72 @@ function mcl_buckets.register_liquid(itemname, def) else return itemstack end + + -- Check if pointing to a buildable node + --local item = itemstack:get_name() + + --[[ + if buildable_to_1 then + if can_place(pos) then + Place + end + else if buildable_to_2 then + if can_place2() then + Place + end + end + ]] + --[[ + if result then -- Fail placement of liquid if result is false + local pns = user:get_player_name() + if minetest.is_protected(place_pos, pns) then + minetest.record_protection_violation(place_pos, pns) + return itemstack + end + place_liquid(place_pos, node_place) + if mod_doc and doc.entry_exists("nodes", node_place) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) + end + else + -- not buildable to; place the liquid above + -- check if the node above can be replaced + local abovenode = minetest.get_node(pointed_thing.above) + if minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to then + local pn = user:get_player_name() + if minetest.is_protected(pointed_thing.above, pn) then + minetest.record_protection_violation(pointed_thing.above, pn) + return itemstack + end + place_liquid(pointed_thing.above, node_place) + if mod_doc and doc.entry_exists("nodes", node_place) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) + end + else + -- do not remove the bucket with the liquid + return + end + end + + -- Handle bucket item and inventory stuff + if not minetest.is_creative_enabled(user:get_player_name()) then + -- Add empty bucket and put it into inventory, if possible. + -- Drop empty bucket otherwise. + local new_bucket = ItemStack("mcl_buckets:bucket_empty") + if itemstack:get_count() == 1 then + return new_bucket + else + local inv = user:get_inventory() + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) + else + minetest.add_item(user:get_pos(), new_bucket) + end + itemstack:take_item() + return itemstack + end + else + return + end]] end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" @@ -256,6 +326,80 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { inventory_image = "bucket.png", stack_max = 16, on_place = function(itemstack, user, pointed_thing) + --[[-- Must be pointing to node + if pointed_thing.type ~= "node" then + return itemstack + end + + -- Call on_rightclick if the pointed node defines it + + + local pointed_liquid = bucket_raycast(user) + + -- Can't steal liquids + if minetest.is_protected(pointed_liquid.above, user:get_player_name()) then + minetest.record_protection_violation(pointed_liquid.under, user:get_player_name()) + return itemstack + end + if minetest.is_protected(pointed_thing.above, user:get_player_name()) then + minetest.record_protection_violation(pointed_thing.under, user:get_player_name()) + return itemstack + end + + -- Check if pointing to a liquid source + local liquiddef = mcl_buckets.liquids[nn] + local new_bucket + if liquiddef and liquiddef.itemname and (nn == liquiddef.source_take) then + + -- 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.on_take then + liquiddef.on_take(user) + end + end + + minetest.add_node(pointed_thing.under, {name="air"}) + sound_take(nn, pointed_thing.under) + + if mod_doc and doc.entry_exists("nodes", nn) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn) + end + + elseif nn == "mcl_cauldrons:cauldron_3" then + -- Take water out of full cauldron + minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + if not minetest.is_creative_enabled(user:get_player_name()) then + new_bucket = ItemStack("mcl_buckets:bucket_water") + end + sound_take("mcl_core:water_source", pointed_thing.under) + elseif nn == "mcl_cauldrons:cauldron_3r" then + -- Take river water out of full cauldron + minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + if not minetest.is_creative_enabled(user:get_player_name()) then + new_bucket = ItemStack("mcl_buckets:bucket_river_water") + end + sound_take("mclx_core:river_water_source", pointed_thing.under) + end + + -- Add liquid bucket and put it into inventory, if possible. + -- Drop new bucket otherwise. + if new_bucket then + if itemstack:get_count() == 1 then + return new_bucket + else + local inv = user:get_inventory() + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) + else + minetest.add_item(user:get_pos(), new_bucket) + end + if not minetest.is_creative_enabled(user:get_player_name()) then + itemstack:take_item() + end + return itemstack + end + end]] -- Must be pointing to node if pointed_thing.type ~= "node" then return itemstack diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index 46abce1d0..97349533e 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -19,7 +19,7 @@ end]] if mod_mcl_core then -- Lava bucket - mcl_buckets.register_liquid("mcl_buckets:bucket_lava", { + mcl_buckets.register_liquid({ source_place = function(pos) local dim = mcl_worlds.pos_to_dimension(pos) if dim == "nether" then @@ -34,6 +34,7 @@ if mod_mcl_core then awards.unlock(user:get_player_name(), "mcl:hotStuff") end end, + itemname = "mcl_buckets:bucket_lava", inventory_image = "bucket_lava.png", name = S("Lava Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."), @@ -42,9 +43,10 @@ if mod_mcl_core then }) -- Water bucket - mcl_buckets.register_liquid("mcl_buckets:bucket_water", { + mcl_buckets.register_liquid({ source_place = "mcl_core:water_source", source_take = {"mcl_core:water_source"}, + itemname = "mcl_buckets:bucket_water", inventory_image = "bucket_water.png", name = S("Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with water."), @@ -75,9 +77,10 @@ end if mod_mclx_core then -- River water bucket - mcl_buckets.register_liquid("mcl_buckets:bucket_river_water", { + mcl_buckets.register_liquid({ source_place = "mclx_core:river_water_source", source_take = {"mclx_core:river_water_source"}, + itemname = "mcl_buckets:bucket_river_water", inventory_image = "bucket_river_water.png", name = S("River Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with river water."), From ec6086d8e631fc19bd9dfca43eb5109f3125d0e4 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 15:14:23 +0200 Subject: [PATCH 024/111] cleanup --- mods/ITEMS/mcl_buckets/init.lua | 140 -------------------------------- 1 file changed, 140 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index b75c10696..312669c5e 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -235,72 +235,6 @@ function mcl_buckets.register_liquid(def) else return itemstack end - - -- Check if pointing to a buildable node - --local item = itemstack:get_name() - - --[[ - if buildable_to_1 then - if can_place(pos) then - Place - end - else if buildable_to_2 then - if can_place2() then - Place - end - end - ]] - --[[ - if result then -- Fail placement of liquid if result is false - local pns = user:get_player_name() - if minetest.is_protected(place_pos, pns) then - minetest.record_protection_violation(place_pos, pns) - return itemstack - end - place_liquid(place_pos, node_place) - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end - else - -- not buildable to; place the liquid above - -- check if the node above can be replaced - local abovenode = minetest.get_node(pointed_thing.above) - if minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to then - local pn = user:get_player_name() - if minetest.is_protected(pointed_thing.above, pn) then - minetest.record_protection_violation(pointed_thing.above, pn) - return itemstack - end - place_liquid(pointed_thing.above, node_place) - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end - else - -- do not remove the bucket with the liquid - return - end - end - - -- Handle bucket item and inventory stuff - if not minetest.is_creative_enabled(user:get_player_name()) then - -- Add empty bucket and put it into inventory, if possible. - -- Drop empty bucket otherwise. - local new_bucket = ItemStack("mcl_buckets:bucket_empty") - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) - else - minetest.add_item(user:get_pos(), new_bucket) - end - itemstack:take_item() - return itemstack - end - else - return - end]] end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" @@ -326,80 +260,6 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { inventory_image = "bucket.png", stack_max = 16, on_place = function(itemstack, user, pointed_thing) - --[[-- Must be pointing to node - if pointed_thing.type ~= "node" then - return itemstack - end - - -- Call on_rightclick if the pointed node defines it - - - local pointed_liquid = bucket_raycast(user) - - -- Can't steal liquids - if minetest.is_protected(pointed_liquid.above, user:get_player_name()) then - minetest.record_protection_violation(pointed_liquid.under, user:get_player_name()) - return itemstack - end - if minetest.is_protected(pointed_thing.above, user:get_player_name()) then - minetest.record_protection_violation(pointed_thing.under, user:get_player_name()) - return itemstack - end - - -- Check if pointing to a liquid source - local liquiddef = mcl_buckets.liquids[nn] - local new_bucket - if liquiddef and liquiddef.itemname and (nn == liquiddef.source_take) then - - -- 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.on_take then - liquiddef.on_take(user) - end - end - - minetest.add_node(pointed_thing.under, {name="air"}) - sound_take(nn, pointed_thing.under) - - if mod_doc and doc.entry_exists("nodes", nn) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn) - end - - elseif nn == "mcl_cauldrons:cauldron_3" then - -- Take water out of full cauldron - minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) - if not minetest.is_creative_enabled(user:get_player_name()) then - new_bucket = ItemStack("mcl_buckets:bucket_water") - end - sound_take("mcl_core:water_source", pointed_thing.under) - elseif nn == "mcl_cauldrons:cauldron_3r" then - -- Take river water out of full cauldron - minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) - if not minetest.is_creative_enabled(user:get_player_name()) then - new_bucket = ItemStack("mcl_buckets:bucket_river_water") - end - sound_take("mclx_core:river_water_source", pointed_thing.under) - end - - -- Add liquid bucket and put it into inventory, if possible. - -- Drop new bucket otherwise. - if new_bucket then - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) - else - minetest.add_item(user:get_pos(), new_bucket) - end - if not minetest.is_creative_enabled(user:get_player_name()) then - itemstack:take_item() - end - return itemstack - end - end]] -- Must be pointing to node if pointed_thing.type ~= "node" then return itemstack From 8fff20eec9f1045c9d16d2a4cdb79c989d627966 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 15:18:12 +0200 Subject: [PATCH 025/111] fix misleading API --- mods/ITEMS/mcl_buckets/init.lua | 12 ++++++------ mods/ITEMS/mcl_buckets/register.lua | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 312669c5e..17d333485 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -153,7 +153,7 @@ function mcl_buckets.register_liquid(def) source_place = def.source_place, source_take = source, on_take = def.on_take, - itemname = def.itemname, + bucketname = def.bucketname, } pointable_sources[source] = true if type(def.source_place) == "string" then @@ -161,11 +161,11 @@ function mcl_buckets.register_liquid(def) end end - if def.itemname == nil or def.itemname == "" then + if def.bucketname == nil or def.bucketname == "" then error(string.format("[mcl_bucket] Invalid itemname then registering [%s]!", def.name)) end - minetest.register_craftitem(def.itemname, { + minetest.register_craftitem(def.bucketname, { description = def.name, _doc_items_longdesc = def.longdesc, _doc_items_usagehelp = def.usagehelp, @@ -289,7 +289,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { -- FIXME: remove this line --if not minetest.is_creative_enabled(user:get_player_name()) then if not false then - new_bucket = ItemStack({name = liquid_def.itemname}) + new_bucket = ItemStack({name = liquid_def.bucketname}) if liquid_def.on_take then liquid_def.on_take(user) end @@ -337,9 +337,9 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { local liquiddef = mcl_buckets.liquids[dropnode.name] local new_bucket - if liquiddef and liquiddef.itemname and (dropnode.name == liquiddef.source_take) then + if liquiddef and liquiddef.bucketname and (dropnode.name == liquiddef.source_take) then -- Fill bucket - new_bucket = ItemStack({name = liquiddef.itemname}) + new_bucket = ItemStack({name = liquiddef.bucketname}) sound_take(dropnode.name, droppos) collect_liquid = true end diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index 97349533e..1a7c8fe14 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -34,7 +34,7 @@ if mod_mcl_core then awards.unlock(user:get_player_name(), "mcl:hotStuff") end end, - itemname = "mcl_buckets:bucket_lava", + bucketname = "mcl_buckets:bucket_lava", inventory_image = "bucket_lava.png", name = S("Lava Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."), @@ -46,7 +46,7 @@ if mod_mcl_core then mcl_buckets.register_liquid({ source_place = "mcl_core:water_source", source_take = {"mcl_core:water_source"}, - itemname = "mcl_buckets:bucket_water", + bucketname = "mcl_buckets:bucket_water", inventory_image = "bucket_water.png", name = S("Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with water."), @@ -80,7 +80,7 @@ if mod_mclx_core then mcl_buckets.register_liquid({ source_place = "mclx_core:river_water_source", source_take = {"mclx_core:river_water_source"}, - itemname = "mcl_buckets:bucket_river_water", + bucketname = "mcl_buckets:bucket_river_water", inventory_image = "bucket_river_water.png", name = S("River Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with river water."), From 873a1e73dc58bf38ca4738feb86f4f4ab8c5d2ba Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 14 Jul 2021 15:22:27 +0200 Subject: [PATCH 026/111] fix documentation --- mods/ITEMS/mcl_buckets/API.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/API.md b/mods/ITEMS/mcl_buckets/API.md index abbdb0a07..94ec48de5 100644 --- a/mods/ITEMS/mcl_buckets/API.md +++ b/mods/ITEMS/mcl_buckets/API.md @@ -9,7 +9,7 @@ Accept folowing params: * 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) +* bucketname: itemstring of the new bucket item * inventory_image: texture of the new bucket item (ignored if itemname == nil) * name: user-visible bucket description * longdesc: long explanatory description (for help) @@ -22,7 +22,7 @@ Accept folowing params: **Usage exemple:** ```lua mcl_buckets.register_liquid({ - itemname = "dummy:bucket_dummy", + bucketname = "dummy:bucket_dummy", --source_place = "dummy:dummy_source", source_place = function(pos) if condition then From dc17cc91a3ea225936869d1f01b1bed498efd0e8 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Thu, 15 Jul 2021 00:01:56 +0200 Subject: [PATCH 027/111] make raycast start from player head --- mods/ITEMS/mcl_buckets/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 17d333485..f1d131ea2 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -81,7 +81,7 @@ local pointable_sources = {} local function bucket_raycast(user) --local pos = user:get_pos() - local pos = mcl_util.get_object_center(user) + local pos = user:get_pos() --local pos = vector.add(user:get_pos(), user:get_bone_position("Head_Control")) pos.y = pos.y + user:get_properties().eye_height local look_dir = user:get_look_dir() From 49bde37a5e80a91f7ad0f03ef371aa32cf7972b8 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Thu, 15 Jul 2021 01:03:50 +0200 Subject: [PATCH 028/111] rewrite README to markdown --- mods/ITEMS/mcl_buckets/{README.txt => README.md} | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) rename mods/ITEMS/mcl_buckets/{README.txt => README.md} (67%) diff --git a/mods/ITEMS/mcl_buckets/README.txt b/mods/ITEMS/mcl_buckets/README.md similarity index 67% rename from mods/ITEMS/mcl_buckets/README.txt rename to mods/ITEMS/mcl_buckets/README.md index 06862d589..b783cc133 100644 --- a/mods/ITEMS/mcl_buckets/README.txt +++ b/mods/ITEMS/mcl_buckets/README.md @@ -1,9 +1,12 @@ -Bucket mod. -Originally taken from Minetest Game, adapted for MineClone 2. +# MineClone2 Bucket (`mcl_bucket`) +Originally taken from Minetest Game, adapted for MineClone2. + +This mod add buckets to the game, including an API to register your own (see `API.md`). + +## License -License of source code: ------------------------ Copyright (C) 2011-2012 Kahrl + Copyright (C) 2011-2012 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify From 9d9e21301271da166248a2356b81e0225d738fde Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 10 Jul 2021 10:54:59 +0200 Subject: [PATCH 029/111] Fix some implicit hard and soft-dependencies These issues were found while testing minetest#8603 and are caused by relying on the undefined mod loading order --- mods/ITEMS/mcl_armor/mod.conf | 2 +- mods/ITEMS/mcl_brewing/mod.conf | 2 +- mods/PLAYER/mcl_playerplus/mod.conf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_armor/mod.conf b/mods/ITEMS/mcl_armor/mod.conf index 9264e8362..fad2e494c 100644 --- a/mods/ITEMS/mcl_armor/mod.conf +++ b/mods/ITEMS/mcl_armor/mod.conf @@ -1,5 +1,5 @@ name = mcl_armor author = stu description = Adds craftable armor that is visible to other players. -depends = mcl_core, mcl_player, mcl_enchanting +depends = mcl_core, mcl_player, mcl_enchanting, mcl_damage optional_depends = mcl_fire, ethereal, bakedclay diff --git a/mods/ITEMS/mcl_brewing/mod.conf b/mods/ITEMS/mcl_brewing/mod.conf index 2c27c979e..0f6217f09 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 -optional_depends = mcl_core, doc, screwdriver +optional_depends = mcl_core, doc, screwdriver, mesecons_mvps diff --git a/mods/PLAYER/mcl_playerplus/mod.conf b/mods/PLAYER/mcl_playerplus/mod.conf index 6989957d7..b77c9e2e5 100644 --- a/mods/PLAYER/mcl_playerplus/mod.conf +++ b/mods/PLAYER/mcl_playerplus/mod.conf @@ -1,5 +1,5 @@ name = mcl_playerplus author = TenPlus1 description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more. -depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage +depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage, mcl_sprint From 60fcafeee4fdeb9a236f141801fc95e103685178 Mon Sep 17 00:00:00 2001 From: Tianyang Zhang Date: Thu, 15 Jul 2021 19:25:32 -0700 Subject: [PATCH 030/111] Update description of emerald --- mods/ITEMS/mcl_core/craftitems.lua | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.de.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.es.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.fr.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.pl.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.ru.tr | 2 +- mods/ITEMS/mcl_core/locale/template.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/mcl_core/craftitems.lua b/mods/ITEMS/mcl_core/craftitems.lua index 03f30b7b9..836f21688 100644 --- a/mods/ITEMS/mcl_core/craftitems.lua +++ b/mods/ITEMS/mcl_core/craftitems.lua @@ -93,7 +93,7 @@ minetest.register_craftitem("mcl_core:gold_ingot", { minetest.register_craftitem("mcl_core:emerald", { description = S("Emerald"), - _doc_items_longdesc = S("Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting."), + _doc_items_longdesc = S("Emeralds are used for trading with villagers."), inventory_image = "mcl_core_emerald.png", stack_max = 64, groups = { craftitem=1 }, diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr index 0a1cbad37..f5a28c76f 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Smaragd Emerald Ore=Smaragderz Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Smaragderz ist das Erz von Smaragden. Es ist sehr selten und kann nur einzeln gefunden werden, nicht in Ansammlungen. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Smaragde sind nicht besonders nützlich, aber man kann sie in der Fertigung durch Goldbarren eintauschen. +Emeralds are used for trading with villagers.=Smaragde sind nicht besonders nützlich, aber man kann sie in der Fertigung durch Goldbarren eintauschen. Flint=Feuerstein Flint is a raw material.=Feuerstein ist ein Rohstoff. Flowing Lava=Fließende Lava diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr index 1e1029c0f..54ee95d16 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Esmeralda Emerald Ore=Mena de esmeralda Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=El mineral esmeralda es el mineral de las esmeraldas. Es muy raro y se puede encontrar solo, no en grupos. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Las esmeraldas no son muy útiles por sí mismas, pero pueden cambiarse por lingotes de oro haciendo artesanías. +Emeralds are used for trading with villagers.=Las esmeraldas no son muy útiles por sí mismas, pero pueden cambiarse por lingotes de oro haciendo artesanías. Flint=Pedernal Flint is a raw material.=El pedernal es una materia prima. Flowing Lava=Lava que fluye diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr index 725025e48..84657c8a1 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Emeraude Emerald Ore=Minerai d'Emeraude Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Le minerai d'émeraude produit des émeraudes. Il est très rare et peut être trouvé seul, pas en filons. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Les émeraudes ne sont pas très utiles seules, mais elles peuvent être échangées contre des lingots d'or. +Emeralds are used for trading with villagers.=Les émeraudes ne sont pas très utiles seules, mais elles peuvent être échangées contre des lingots d'or. Flint=Silex Flint is a raw material.=Le silex est une matière première. Flowing Lava=Lave qui coule diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr index 832a47830..90a75f810 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Szmaragd Emerald Ore=Ruda szmaragdu Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Ruda szmaragdu jest bardzo rzadka i występuje samotnie, nie w grupach. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Szmaragdy nie są zbyt użyteczne same w sobie, ale można z nich wytworzyć sztabki złota. +Emeralds are used for trading with villagers.=Szmaragdy nie są zbyt użyteczne same w sobie, ale można z nich wytworzyć sztabki złota. Flint=Krzemień Flint is a raw material.=Krzemień jest surowym materiałem. Flowing Lava=Płynąca lawa diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr index f93db7c2c..07236037b 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Изумруд Emerald Ore=Изумрудная руда Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Изумрудная руда встречается очень редко и всегда по одному блоку. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Изумруды не очень полезны сами по себе, но их можно обменять на золотые слитки. +Emeralds are used for trading with villagers.=Изумруды не очень полезны сами по себе, но их можно обменять на золотые слитки. Flint=Кремень Flint is a raw material.=Кремень это необработанный материал. Flowing Lava=Текущая лава diff --git a/mods/ITEMS/mcl_core/locale/template.txt b/mods/ITEMS/mcl_core/locale/template.txt index 2cb74f5d1..1e8ee04ce 100644 --- a/mods/ITEMS/mcl_core/locale/template.txt +++ b/mods/ITEMS/mcl_core/locale/template.txt @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald= Emerald Ore= Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.= -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.= +Emeralds are used for trading with villagers.= Flint= Flint is a raw material.= Flowing Lava= From b364faa7c7d76370953f798e207837f4e6b7cfab Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 17 Jul 2021 16:22:46 +0200 Subject: [PATCH 031/111] make bucket use 5 lenght raycast --- mods/ITEMS/mcl_buckets/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index f1d131ea2..931214b95 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -85,7 +85,7 @@ local function bucket_raycast(user) --local pos = vector.add(user:get_pos(), user:get_bone_position("Head_Control")) pos.y = pos.y + user:get_properties().eye_height local look_dir = user:get_look_dir() - look_dir = vector.multiply(look_dir, 4) + look_dir = vector.multiply(look_dir, 5) local pos2 = vector.add(pos, look_dir) local ray = raycast(pos, pos2, false, true) From 48166625d4ddba283d0ca5dca9c548dfb0595337 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 18 Jul 2021 17:21:53 +0000 Subject: [PATCH 032/111] Add mcl_item_id mod --- mods/HELP/mcl_item_id/init.lua | 35 ++++++++++++++++++++++++++++++++++ mods/HELP/mcl_item_id/mod.conf | 3 +++ 2 files changed, 38 insertions(+) create mode 100644 mods/HELP/mcl_item_id/init.lua create mode 100644 mods/HELP/mcl_item_id/mod.conf diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua new file mode 100644 index 000000000..1d165d8c6 --- /dev/null +++ b/mods/HELP/mcl_item_id/init.lua @@ -0,0 +1,35 @@ +local game = "mineclone2" + +local same_id = { + heads = { "skeleton", "zombie", "creeper", "wither_skeleton" }, + mobitems = { "rabbit", "chicken" }, + walls = { + "andesite", "brick", "cobble", "diorite", "endbricks", + "granite", "mossycobble", "netherbrick", "prismarine", + "rednetherbrick", "redsandstone", "sandstone", + "stonebrick", "stonebrickmossy", + }, + wool = { + "black", "blue", "brown", "cyan", "green", + "grey", "light_blue", "lime", "magenta", "orange", + "pink", "purple", "red", "silver", "white", "yellow", + }, +} + +tt.register_snippet(function(itemstring) + local def = minetest.registered_items[itemstring] + local desc = def.description + local item_split = itemstring:find(":") + local new_id = game .. itemstring:sub(item_split) + for mod, ids in pairs(same_id) do + for _, id in pairs(ids) do + if itemstring == "mcl_" .. mod .. ":" .. id then + new_id = game .. ":" .. id .. "_" .. mod:gsub("s", "") + end + end + end + minetest.register_alias(new_id, itemstring) + if minetest.settings:get_bool("mcl_item_id_debug", true) then + return new_id, "#555555" + end +end) diff --git a/mods/HELP/mcl_item_id/mod.conf b/mods/HELP/mcl_item_id/mod.conf new file mode 100644 index 000000000..c45e17fd3 --- /dev/null +++ b/mods/HELP/mcl_item_id/mod.conf @@ -0,0 +1,3 @@ +name = mcl_item_id +author = NO11 +depends = tt \ No newline at end of file From f2a4d6bd561a6499ea24875c23046340b8b572e0 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 18 Jul 2021 17:23:12 +0000 Subject: [PATCH 033/111] Add item id setting --- settingtypes.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/settingtypes.txt b/settingtypes.txt index ea1c1a50a..f605019ad 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -153,3 +153,7 @@ fix_doubleplants (Mcimport double plant fixes) bool true # Allow players to create Minecraft-like maps. enable_real_maps (Enable Real Maps) bool true + +[Debugging] +# If enabled, this will show the itemstring of an item in the description. +mcl_item_id_debug (Item ID Debug) bool false \ No newline at end of file From 801d9a25715ee5ac1f7a99fc24b0b78fd4b60814 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 18 Jul 2021 18:01:55 +0000 Subject: [PATCH 034/111] Remove some spaces --- mods/HELP/mcl_item_id/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index 1d165d8c6..e715ac9e9 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -17,7 +17,7 @@ local same_id = { } tt.register_snippet(function(itemstring) - local def = minetest.registered_items[itemstring] + local def = minetest.registered_items[itemstring] local desc = def.description local item_split = itemstring:find(":") local new_id = game .. itemstring:sub(item_split) From 96e8e6a86f00835d2e7d5dc36974ec5cfcf2a919 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 19 Jul 2021 12:21:30 +0000 Subject: [PATCH 035/111] Use mineclone: instead of mineclone2: for item IDs --- mods/HELP/mcl_item_id/init.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index e715ac9e9..e7772d141 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -1,4 +1,4 @@ -local game = "mineclone2" +local game = "mineclone" local same_id = { heads = { "skeleton", "zombie", "creeper", "wither_skeleton" }, @@ -30,6 +30,6 @@ tt.register_snippet(function(itemstring) end minetest.register_alias(new_id, itemstring) if minetest.settings:get_bool("mcl_item_id_debug", true) then - return new_id, "#555555" - end + return new_id, "#555555" + end end) From 559cf85c9449b77591603ca561618668a3fb027e Mon Sep 17 00:00:00 2001 From: Tianyang Zhang Date: Mon, 19 Jul 2021 09:12:39 -0700 Subject: [PATCH 036/111] Improve description of emerald --- mods/ITEMS/mcl_core/craftitems.lua | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.de.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.es.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.fr.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.pl.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.ru.tr | 2 +- mods/ITEMS/mcl_core/locale/template.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/mcl_core/craftitems.lua b/mods/ITEMS/mcl_core/craftitems.lua index 836f21688..85a078766 100644 --- a/mods/ITEMS/mcl_core/craftitems.lua +++ b/mods/ITEMS/mcl_core/craftitems.lua @@ -93,7 +93,7 @@ minetest.register_craftitem("mcl_core:gold_ingot", { minetest.register_craftitem("mcl_core:emerald", { description = S("Emerald"), - _doc_items_longdesc = S("Emeralds are used for trading with villagers."), + _doc_items_longdesc = S("Emeralds are used in villager trades as currency."), inventory_image = "mcl_core_emerald.png", stack_max = 64, groups = { craftitem=1 }, diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr index f5a28c76f..8b75dfd40 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Smaragd Emerald Ore=Smaragderz Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Smaragderz ist das Erz von Smaragden. Es ist sehr selten und kann nur einzeln gefunden werden, nicht in Ansammlungen. -Emeralds are used for trading with villagers.=Smaragde sind nicht besonders nützlich, aber man kann sie in der Fertigung durch Goldbarren eintauschen. +Emeralds are used in villager trades as currency.=Smaragde sind nicht besonders nützlich, aber man kann sie in der Fertigung durch Goldbarren eintauschen. Flint=Feuerstein Flint is a raw material.=Feuerstein ist ein Rohstoff. Flowing Lava=Fließende Lava diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr index 54ee95d16..d77f45dc2 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Esmeralda Emerald Ore=Mena de esmeralda Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=El mineral esmeralda es el mineral de las esmeraldas. Es muy raro y se puede encontrar solo, no en grupos. -Emeralds are used for trading with villagers.=Las esmeraldas no son muy útiles por sí mismas, pero pueden cambiarse por lingotes de oro haciendo artesanías. +Emeralds are used in villager trades as currency.=Las esmeraldas no son muy útiles por sí mismas, pero pueden cambiarse por lingotes de oro haciendo artesanías. Flint=Pedernal Flint is a raw material.=El pedernal es una materia prima. Flowing Lava=Lava que fluye diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr index 84657c8a1..4d6a3ed43 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Emeraude Emerald Ore=Minerai d'Emeraude Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Le minerai d'émeraude produit des émeraudes. Il est très rare et peut être trouvé seul, pas en filons. -Emeralds are used for trading with villagers.=Les émeraudes ne sont pas très utiles seules, mais elles peuvent être échangées contre des lingots d'or. +Emeralds are used in villager trades as currency.=Les émeraudes ne sont pas très utiles seules, mais elles peuvent être échangées contre des lingots d'or. Flint=Silex Flint is a raw material.=Le silex est une matière première. Flowing Lava=Lave qui coule diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr index 90a75f810..f8dbbde6b 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Szmaragd Emerald Ore=Ruda szmaragdu Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Ruda szmaragdu jest bardzo rzadka i występuje samotnie, nie w grupach. -Emeralds are used for trading with villagers.=Szmaragdy nie są zbyt użyteczne same w sobie, ale można z nich wytworzyć sztabki złota. +Emeralds are used in villager trades as currency.=Szmaragdy nie są zbyt użyteczne same w sobie, ale można z nich wytworzyć sztabki złota. Flint=Krzemień Flint is a raw material.=Krzemień jest surowym materiałem. Flowing Lava=Płynąca lawa diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr index 07236037b..ad9d863b2 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Изумруд Emerald Ore=Изумрудная руда Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Изумрудная руда встречается очень редко и всегда по одному блоку. -Emeralds are used for trading with villagers.=Изумруды не очень полезны сами по себе, но их можно обменять на золотые слитки. +Emeralds are used in villager trades as currency.=Изумруды не очень полезны сами по себе, но их можно обменять на золотые слитки. Flint=Кремень Flint is a raw material.=Кремень это необработанный материал. Flowing Lava=Текущая лава diff --git a/mods/ITEMS/mcl_core/locale/template.txt b/mods/ITEMS/mcl_core/locale/template.txt index 1e8ee04ce..19d156711 100644 --- a/mods/ITEMS/mcl_core/locale/template.txt +++ b/mods/ITEMS/mcl_core/locale/template.txt @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald= Emerald Ore= Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.= -Emeralds are used for trading with villagers.= +Emeralds are used in villager trades as currency.= Flint= Flint is a raw material.= Flowing Lava= From 999b82c94a167cdb62d2894fe45718bd48a91ce9 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 20 Jul 2021 15:21:07 +0200 Subject: [PATCH 037/111] small documentation graphical improvement --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b5098a4f..4c9bf3e38 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,17 +52,17 @@ Each mod must provide `mod.conf`. Each mod which add API functions should store functions inside a global table named like the mod. Public functions should not use self references but rather just access the table directly. Functions should be defined in this way: -``` +```lua function mcl_xyz.stuff(param) end ``` Insteed of this way: -``` +```lua mcl_xyz.stuff = function(param) end ``` Indentation must be unified, more likely with tabs. Time sensitive mods should make a local copy of most used API functions to improve performances. -``` +```lua local vector = vector local get_node = minetest.get_node ``` From b5f7ae54583197b55bb5e8f5f81a6605fa4f74e8 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 20 Jul 2021 15:47:26 +0200 Subject: [PATCH 038/111] working implementation + support of other mods --- mods/ENTITIES/mcl_boats/init.lua | 2 +- mods/ENTITIES/mcl_boats/mod.conf | 2 +- mods/ENTITIES/mcl_minecarts/init.lua | 2 +- mods/ENTITIES/mcl_minecarts/mod.conf | 2 +- mods/HUD/mcl_title/init.lua | 5 ++--- mods/ITEMS/mcl_beds/functions.lua | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index 76ace7a45..e81e9ffc5 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -84,7 +84,7 @@ local function attach_object(self, obj) end end, name) obj:set_look_horizontal(yaw) - mcl_tmp_message.message(obj, S("Sneak to dismount")) + mcl_title.set(obj, "actionbar", {text=S("Sneak to dismount"), color="white", stay=3}) else obj:get_luaentity()._old_visual_size = visual_size end diff --git a/mods/ENTITIES/mcl_boats/mod.conf b/mods/ENTITIES/mcl_boats/mod.conf index a5d6cc8cb..61463b6ec 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, flowlib +depends = mcl_player, flowlib, mcl_title optional_depends = mcl_core, doc_identifier diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index e33e120a1..a76ab538a 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -646,7 +646,7 @@ register_minecart( if player then mcl_player.player_set_animation(player, "sit" , 30) player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0}) - mcl_tmp_message.message(clicker, S("Sneak to dismount")) + mcl_title.set(clicker, "actionbar", {text=S("Sneak to dismount"), color="white", stay=3}) end end, name) end diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 9fff9175d..3b8ae5551 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 +depends = mcl_title, 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 diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 48c3a909f..03fe17614 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -45,7 +45,7 @@ local player_params = {} minetest.register_on_joinplayer(function(player) local playername = player:get_player_name() - player_params[playername] = { + player_params[player] = { stay = gametick_to_secondes(mcl_title.defaults.stay), --fadeIn = gametick_to_secondes(mcl_title.defaults.fadein), --fadeOut = gametick_to_secondes(mcl_title.defaults.fadeout), @@ -127,14 +127,13 @@ function mcl_title.set(player, type, data) return false end - --TODO: enable this code then Fleckenstein's pr get merged (in about 5-6 years) + --TODO: enable this code then Fleckenstein's pr get merged (in about 5-6 years lol) --if data.bold == nil then data.bold = false end --if data.italic == nil then data.italic = false end player:hud_change(huds_idx[type][player], "text", data.text) player:hud_change(huds_idx[type][player], "number", hex_color) - hud_hide_timeouts[type][player:get_player_name()] = data.stay or mcl_title.params_get(player).stay return true end diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index dc9afe2ba..f323ca4c7 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -330,7 +330,7 @@ function mcl_beds.on_rightclick(pos, player, is_top) message = select(2, lay_down(player, ppos, other)) end if message then - mcl_tmp_message.message(player, message) + mcl_title.set(player, "actionbar", {text=message, color="white", stay=3}) end else lay_down(player, nil, nil, false) From c31c852a6ea63eb2ffed49089881866fb59df0ed Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 20 Jul 2021 16:14:34 +0200 Subject: [PATCH 039/111] add documentation --- mods/ENTITIES/mcl_boats/init.lua | 2 +- mods/ENTITIES/mcl_minecarts/init.lua | 2 +- mods/HUD/mcl_title/API.md | 42 ++++++++++++++++++++++++++++ mods/HUD/mcl_title/init.lua | 2 +- mods/ITEMS/mcl_beds/functions.lua | 2 +- 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 mods/HUD/mcl_title/API.md diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index e81e9ffc5..311b07882 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -84,7 +84,7 @@ local function attach_object(self, obj) end end, name) obj:set_look_horizontal(yaw) - mcl_title.set(obj, "actionbar", {text=S("Sneak to dismount"), color="white", stay=3}) + mcl_title.set(obj, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60}) else obj:get_luaentity()._old_visual_size = visual_size end diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index a76ab538a..4d3873cc2 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -646,7 +646,7 @@ register_minecart( if player then mcl_player.player_set_animation(player, "sit" , 30) player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0}) - mcl_title.set(clicker, "actionbar", {text=S("Sneak to dismount"), color="white", stay=3}) + mcl_title.set(clicker, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60}) end end, name) end diff --git a/mods/HUD/mcl_title/API.md b/mods/HUD/mcl_title/API.md new file mode 100644 index 000000000..50614be4f --- /dev/null +++ b/mods/HUD/mcl_title/API.md @@ -0,0 +1,42 @@ +# mcl_title + +Allow mods to show messages in the hud of players. + +## mcl_title.set(player, type, data) + +Show a hud message of `type` to player `player` with `data` as params. + +The element will stay for the per-player param `stay` or `data.stay` (in gametick which is 1/20 second). + +Here is a usage exemple: + +```lua +--show a title in the HUD with minecraft color "gold" +mcl_title.set(player, "title", {text="dummy text", color="gold"}) + +--show a subtitle in the HUD with hex color "#612D2D" +mcl_title.set(player, "subtitle", {text="dummy subtitle", color="#612D2D"}) + +--show an actionbar in the HUD (above the hotbar) with minecraft color "red" +mcl_title.set(player, "subtitle", {text="dummy actionbar", color="red"}) + +--show a title in the HUD with minecraft color "gold" staying for 3 seconds (override stay setting) +mcl_title.set(player, "title", {text="dummy text", color="gold", stay=3}) +``` + +## mcl_title.remove(player, type) + +Hide HUD element of type `type` for player `player`. + +## mcl_title.clear(player) + +Remove every title/subtitle/actionbar from a player. +Basicaly run `mcl_title.remove(player, type)` for every type. + +## mcl_title.params_set(player, params) + +Allow mods to set `stay` and upcomming `fadeIn`/`fadeOut` params. + +```lua +mcl_title.params_set(player, {stay = 600}) --elements with no 'data.stay' field will stay during 30s (600/20) +``` \ No newline at end of file diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 03fe17614..d1dbece4b 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -134,7 +134,7 @@ function mcl_title.set(player, type, data) player:hud_change(huds_idx[type][player], "text", data.text) player:hud_change(huds_idx[type][player], "number", hex_color) - hud_hide_timeouts[type][player:get_player_name()] = data.stay or mcl_title.params_get(player).stay + hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or mcl_title.params_get(player).stay return true end diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index f323ca4c7..e196f69ad 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -330,7 +330,7 @@ function mcl_beds.on_rightclick(pos, player, is_top) message = select(2, lay_down(player, ppos, other)) end if message then - mcl_title.set(player, "actionbar", {text=message, color="white", stay=3}) + mcl_title.set(player, "actionbar", {text=message, color="white", stay=60}) end else lay_down(player, nil, nil, false) From 31d3ea8a871fef4acbab8493d85768ea7884ac76 Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 20 Jul 2021 20:09:43 +0000 Subject: [PATCH 040/111] Fix #1801 (add better texture for golden boots) --- .../textures/mcl_armor_inv_boots_gold.png | Bin 167 -> 409 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/mods/ITEMS/mcl_armor/textures/mcl_armor_inv_boots_gold.png b/mods/ITEMS/mcl_armor/textures/mcl_armor_inv_boots_gold.png index dc452d41372344c624d15270867e81ea7551b52a..ef1f9fa87ca43be01bc084da406069ce278d3c1f 100644 GIT binary patch delta 382 zcmV-^0fGLf0ht4kB!32COGiWi{{a60|De66lK=n!32;bRa{vG?BLDy{BLR4&KXw2B z00(qQO+^Rg2NVS)N@!D*zX#WvQEA z04#(nBfex{Rjq`aWmi8Z5*|?Csfm&M27np1J9o)$LRS>Zl1E_v~4!`V2#&%;Q32n c`Ir8}H*o=PdJ9oayZ`_I07*qoM6N<$g80X(CIA2c delta 139 zcmV;60CfME1E&FyB!6y6L_t(|0b>|^;Q#;s_%N*uz|=^*L1E2{L6~|5?CR0_55iDB zhB#gWt}HkG|LS1U|0NYl7zO~vz;Ylp*bIQ#0#bm>0I(cT4PFC4nsFKc#25y^G?Rl- t4M^~)Ar`|7ppFYb4017LDUoUb0H9FFs6zF<5C8xG07*qoLI9vb# From a0d52010bf6dcfe3b7fa1175dc5c76923b515eed Mon Sep 17 00:00:00 2001 From: NO11 Date: Wed, 21 Jul 2021 22:16:37 +0000 Subject: [PATCH 041/111] Fix that aliases attemp to register mineclone:book_enchanted again and again --- mods/HELP/mcl_item_id/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index e7772d141..01eb40362 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -28,7 +28,7 @@ tt.register_snippet(function(itemstring) end end end - minetest.register_alias(new_id, itemstring) + minetest.register_alias_force(new_id, itemstring) if minetest.settings:get_bool("mcl_item_id_debug", true) then return new_id, "#555555" end From fef23d0b6f224ed178d109ec5d74137168119421 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Thu, 22 Jul 2021 00:39:05 +0200 Subject: [PATCH 042/111] fix missing depend to `mcl_credits` of `mcl_portals` --- mods/ITEMS/mcl_portals/mod.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_portals/mod.conf b/mods/ITEMS/mcl_portals/mod.conf index d99344a76..610b590c6 100644 --- a/mods/ITEMS/mcl_portals/mod.conf +++ b/mods/ITEMS/mcl_portals/mod.conf @@ -1,4 +1,4 @@ name = mcl_portals description = Adds buildable portals to the Nether and End dimensions. -depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn +depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn, mcl_credits optional_depends = awards, doc From 667ef5cad51684f79debd5a133dc78f3ea29974c Mon Sep 17 00:00:00 2001 From: AFCMS Date: Thu, 22 Jul 2021 00:46:43 +0200 Subject: [PATCH 043/111] cache doc modpath --- mods/ITEMS/mcl_portals/portal_end.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index d591537e1..9f0db352a 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -4,6 +4,8 @@ local table = table local vector = vector local math = math +local has_doc = minetest.get_modpath("doc") + -- Parameters --local SPAWN_MIN = mcl_vars.mg_end_min+70 --local SPAWN_MAX = mcl_vars.mg_end_min+98 @@ -339,7 +341,7 @@ minetest.register_node("mcl_portals:end_portal_frame_eye", { _mcl_hardness = -1, }) -if minetest.get_modpath("doc") then +if has_doc then doc.add_entry_alias("nodes", "mcl_portals:end_portal_frame", "nodes", "mcl_portals:end_portal_frame_eye") end @@ -366,7 +368,7 @@ minetest.override_item("mcl_end:ender_eye", { end minetest.set_node(pointed_thing.under, { name = "mcl_portals:end_portal_frame_eye", param2 = node.param2 }) - if minetest.get_modpath("doc") then + if has_doc then doc.mark_entry_as_revealed(user:get_player_name(), "nodes", "mcl_portals:end_portal_frame") end minetest.sound_play( @@ -381,7 +383,7 @@ minetest.override_item("mcl_end:ender_eye", { -- Epic 'portal open' sound effect that can be heard everywhere minetest.sound_play("mcl_portals_open_end_portal", {gain=0.8}, true) end_portal_area(ppos) - if minetest.get_modpath("doc") then + if has_doc then doc.mark_entry_as_revealed(user:get_player_name(), "nodes", "mcl_portals:portal_end") end end From a44d9643ae8b826f1e5efb67259d6d77320dfade Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 22 Jul 2021 19:23:48 +0000 Subject: [PATCH 044/111] Fix several problems in `mcl_item_id` --- mods/HELP/mcl_item_id/init.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index 01eb40362..3b3128f26 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -28,8 +28,12 @@ tt.register_snippet(function(itemstring) end end end - minetest.register_alias_force(new_id, itemstring) - if minetest.settings:get_bool("mcl_item_id_debug", true) then + if new_id ~= game .. ":book_enchanted" then + minetest.register_alias_force(new_id, itemstring) + end + if minetest.settings:get_bool("mcl_item_id_debug", false) then return new_id, "#555555" end end) + +minetest.register_alias_force(game .. ":book_enchanted", "mcl_enchanting:book_enchanted") From 75b425ffd77b85ba3081ddf2e47f8b6695ec8fa5 Mon Sep 17 00:00:00 2001 From: NO11 Date: Fri, 23 Jul 2021 12:23:30 +0000 Subject: [PATCH 045/111] Fix #1842 make other mods not using "mineclone" name space for item ids --- mods/HELP/mcl_item_id/init.lua | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index 3b3128f26..50247a858 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -1,4 +1,5 @@ local game = "mineclone" +local mcl_mods = {} local same_id = { heads = { "skeleton", "zombie", "creeper", "wither_skeleton" }, @@ -10,17 +11,34 @@ local same_id = { "stonebrick", "stonebrickmossy", }, wool = { - "black", "blue", "brown", "cyan", "green", + "black", "blue", "brown", "cyan", "green", "grey", "light_blue", "lime", "magenta", "orange", "pink", "purple", "red", "silver", "white", "yellow", }, } +local worldmt = io.open(minetest.get_worldpath() .. "/world.mt", "r") +local gameid = worldmt:read("*a"):match("gameid%s*=%s*(%S+)\n") +worldmt:close() + +for _, mod in pairs(minetest.get_modnames()) do + if minetest.get_modpath(mod):match("/games/" .. gameid .. "/") then + table.insert(mcl_mods, mod) + end +end + +local function item_id(id) + if minetest.settings:get_bool("mcl_item_id_debug", false) then + return id, "#555555" + end +end + tt.register_snippet(function(itemstring) local def = minetest.registered_items[itemstring] local desc = def.description local item_split = itemstring:find(":") local new_id = game .. itemstring:sub(item_split) + local mcl_mod = itemstring:sub(1, item_split) for mod, ids in pairs(same_id) do for _, id in pairs(ids) do if itemstring == "mcl_" .. mod .. ":" .. id then @@ -28,12 +46,15 @@ tt.register_snippet(function(itemstring) end end end - if new_id ~= game .. ":book_enchanted" then - minetest.register_alias_force(new_id, itemstring) - end - if minetest.settings:get_bool("mcl_item_id_debug", false) then - return new_id, "#555555" + for _, modname in pairs(mcl_mods) do + if modname .. ":" == mcl_mod then + if new_id ~= game .. ":book_enchanted" and new_id ~= itemstring then + minetest.register_alias_force(new_id, itemstring) + end + return item_id(new_id) + end end + return item_id(itemstring) end) minetest.register_alias_force(game .. ":book_enchanted", "mcl_enchanting:book_enchanted") From 09a68443cd641ed73631cc076916616e518402ea Mon Sep 17 00:00:00 2001 From: NO11 Date: Fri, 23 Jul 2021 16:12:43 +0000 Subject: [PATCH 046/111] Better fix for #1842 (make other mods not using "mineclone" name space for item ids) --- mods/HELP/mcl_item_id/init.lua | 57 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index 50247a858..4e9c7c9f1 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -1,5 +1,20 @@ +mcl_item_id = {} + local game = "mineclone" -local mcl_mods = {} + +function mcl_item_id.set_mod_namespace(modname, namespace) + local namespace = namespace or modname + mcl_item_id[modname .. "_namespace"] = namespace +end + +function mcl_item_id.get_mod_namespace(modname) + local namespace = mcl_item_id[modname .. "_namespace"] + if namespace then + return namespace + else + return "" + end +end local same_id = { heads = { "skeleton", "zombie", "creeper", "wither_skeleton" }, @@ -17,28 +32,15 @@ local same_id = { }, } -local worldmt = io.open(minetest.get_worldpath() .. "/world.mt", "r") -local gameid = worldmt:read("*a"):match("gameid%s*=%s*(%S+)\n") -worldmt:close() - -for _, mod in pairs(minetest.get_modnames()) do - if minetest.get_modpath(mod):match("/games/" .. gameid .. "/") then - table.insert(mcl_mods, mod) - end -end - -local function item_id(id) - if minetest.settings:get_bool("mcl_item_id_debug", false) then - return id, "#555555" - end -end - tt.register_snippet(function(itemstring) local def = minetest.registered_items[itemstring] local desc = def.description local item_split = itemstring:find(":") - local new_id = game .. itemstring:sub(item_split) - local mcl_mod = itemstring:sub(1, item_split) + local id_part1 = itemstring:sub(1, item_split) + local id_part2 = itemstring:sub(item_split) + local modname = id_part1:gsub("%:", "") + local new_id = game .. id_part2 + local mod_namespace = mcl_item_id.get_mod_namespace(modname) for mod, ids in pairs(same_id) do for _, id in pairs(ids) do if itemstring == "mcl_" .. mod .. ":" .. id then @@ -46,15 +48,16 @@ tt.register_snippet(function(itemstring) end end end - for _, modname in pairs(mcl_mods) do - if modname .. ":" == mcl_mod then - if new_id ~= game .. ":book_enchanted" and new_id ~= itemstring then - minetest.register_alias_force(new_id, itemstring) - end - return item_id(new_id) - end + + if mod_namespace then + new_id = mod_namespace .. id_part2 + end + if new_id ~= game .. ":book_enchanted" then + minetest.register_alias_force(new_id, itemstring) + end + if minetest.settings:get_bool("mcl_item_id_debug", false) then + return new_id, "#555555" end - return item_id(itemstring) end) minetest.register_alias_force(game .. ":book_enchanted", "mcl_enchanting:book_enchanted") From e44e9eaf623809bc2fa4c617dd6e9629aa5b3879 Mon Sep 17 00:00:00 2001 From: NO11 Date: Fri, 23 Jul 2021 21:35:10 +0000 Subject: [PATCH 047/111] Fix typo --- mods/HELP/mcl_item_id/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index 4e9c7c9f1..911d8225b 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -12,7 +12,7 @@ function mcl_item_id.get_mod_namespace(modname) if namespace then return namespace else - return "" + return end end From c05e57efb1f3d55c89354c28a84e76abe63aadd5 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 24 Jul 2021 14:09:47 +0000 Subject: [PATCH 048/111] Fix some crashes with set_mod_namespace and bugs --- mods/HELP/mcl_item_id/init.lua | 46 +++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index 911d8225b..9a2f926e8 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -1,22 +1,38 @@ -mcl_item_id = {} +mcl_item_id = { + mod_namespaces = {}, +} local game = "mineclone" function mcl_item_id.set_mod_namespace(modname, namespace) local namespace = namespace or modname - mcl_item_id[modname .. "_namespace"] = namespace + mcl_item_id.mod_namespaces[modname] = namespace + minetest.register_on_mods_loaded(function() + for item, def in pairs(minetest.registered_items) do + local item_split = item:find(":") + if item_split then + local id_modname = item:sub(1, item_split - 1) + local id_string = item:sub(item_split) + if id_modname == modname then + minetest.register_alias_force(namespace .. id_string, item) + end + end + end + end) end function mcl_item_id.get_mod_namespace(modname) - local namespace = mcl_item_id[modname .. "_namespace"] + local namespace = mcl_item_id.mod_namespaces[modname] if namespace then return namespace else - return + return game end end local same_id = { + enchanting = { "table" }, + experience = { "bottle" }, heads = { "skeleton", "zombie", "creeper", "wither_skeleton" }, mobitems = { "rabbit", "chicken" }, walls = { @@ -34,13 +50,11 @@ local same_id = { tt.register_snippet(function(itemstring) local def = minetest.registered_items[itemstring] - local desc = def.description local item_split = itemstring:find(":") - local id_part1 = itemstring:sub(1, item_split) - local id_part2 = itemstring:sub(item_split) - local modname = id_part1:gsub("%:", "") - local new_id = game .. id_part2 - local mod_namespace = mcl_item_id.get_mod_namespace(modname) + local id_string = itemstring:sub(item_split) + local id_modname = itemstring:sub(1, item_split - 1) + local new_id = game .. id_string + local mod_namespace = mcl_item_id.get_mod_namespace(id_modname) for mod, ids in pairs(same_id) do for _, id in pairs(ids) do if itemstring == "mcl_" .. mod .. ":" .. id then @@ -48,16 +62,12 @@ tt.register_snippet(function(itemstring) end end end - - if mod_namespace then - new_id = mod_namespace .. id_part2 - end - if new_id ~= game .. ":book_enchanted" then + if mod_namespace ~= game then + new_id = mod_namespace .. id_string + else minetest.register_alias_force(new_id, itemstring) end if minetest.settings:get_bool("mcl_item_id_debug", false) then return new_id, "#555555" end -end) - -minetest.register_alias_force(game .. ":book_enchanted", "mcl_enchanting:book_enchanted") +end) \ No newline at end of file From 65d33b935ab23e6a43b069c62124d51ead05c165 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 24 Jul 2021 14:45:55 +0000 Subject: [PATCH 049/111] Add API-md for `mcl_item_id` --- mods/HELP/mcl_item_id/API.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 mods/HELP/mcl_item_id/API.md diff --git a/mods/HELP/mcl_item_id/API.md b/mods/HELP/mcl_item_id/API.md new file mode 100644 index 000000000..a2f244e0c --- /dev/null +++ b/mods/HELP/mcl_item_id/API.md @@ -0,0 +1,24 @@ +# mcl_item_id +Show the item ID of an item in the description. +With this API, you can register a different name space than "mineclone" for your mod. + +## mcl_item_id.set_mod_namespace(modname, namespace) +Set a name space for all items in a mod. + +* param1: the modname +* param2: (optional) string of the desired name space, if nil, it is the name of the mod + +## mcl_item_id.get_mod_namespace(modname) +Get the name space of a mod registered with mcl_item_id.set_mod_namespace(modname, namespace). + +* param1: the modname + +### Examples: + +The name of the mod is "mod" which registered an item called "mod:itemname". + +* mcl_item_id.set_mod_namespace("mod", "mymod") will show "mymod:itemname" in the description of "mod:itemname" +* mcl_item_id.set_mod_namespace(minetest.get_current_modname()) will show "mod:itemname" in the description of "mod:itemname" +* mcl_item_id.get_mod_namespace(minetest.get_current_modname()) will return "mod" + +(If no namespace is set by a mod, mcl_item_id.get_mod_namespace(minetest.get_current_modname()) will return "mineclone") From 5c5c405ccf92762af6f0757d4a3b015ff14d0d37 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 24 Jul 2021 15:19:10 +0000 Subject: [PATCH 050/111] Add missing check --- mods/HELP/mcl_item_id/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index 9a2f926e8..e6df1af03 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -13,7 +13,7 @@ function mcl_item_id.set_mod_namespace(modname, namespace) if item_split then local id_modname = item:sub(1, item_split - 1) local id_string = item:sub(item_split) - if id_modname == modname then + if id_modname == modname and modname ~= namespace then minetest.register_alias_force(namespace .. id_string, item) end end From 4846076c8fc2555dff12bf148c5b1d83ab39ec9d Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 24 Jul 2021 19:07:44 +0000 Subject: [PATCH 051/111] `mcl_item_id` simplify code --- mods/HELP/mcl_item_id/init.lua | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua index e6df1af03..f3e6d2735 100644 --- a/mods/HELP/mcl_item_id/init.lua +++ b/mods/HELP/mcl_item_id/init.lua @@ -7,18 +7,6 @@ local game = "mineclone" function mcl_item_id.set_mod_namespace(modname, namespace) local namespace = namespace or modname mcl_item_id.mod_namespaces[modname] = namespace - minetest.register_on_mods_loaded(function() - for item, def in pairs(minetest.registered_items) do - local item_split = item:find(":") - if item_split then - local id_modname = item:sub(1, item_split - 1) - local id_string = item:sub(item_split) - if id_modname == modname and modname ~= namespace then - minetest.register_alias_force(namespace .. id_string, item) - end - end - end - end) end function mcl_item_id.get_mod_namespace(modname) @@ -64,7 +52,8 @@ tt.register_snippet(function(itemstring) end if mod_namespace ~= game then new_id = mod_namespace .. id_string - else + end + if mod_namespace ~= id_modname then minetest.register_alias_force(new_id, itemstring) end if minetest.settings:get_bool("mcl_item_id_debug", false) then From 4aabd7d9e721a860864157ac5145985d8a2360b9 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 1 Aug 2021 12:10:00 +0000 Subject: [PATCH 052/111] Make size/position of potion HUD more MC like --- mods/ITEMS/mcl_potions/functions.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 09b95115a..c3b034b66 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -35,13 +35,13 @@ local function potions_init_icons(player) local name = player:get_player_name() icon_ids[name] = {} for e=1, EFFECT_TYPES do - local x = -7 + -38 * e + local x = -52 * e - 2 local id = player:hud_add({ hud_elem_type = "image", text = "blank.png", position = { x = 1, y = 0 }, - offset = { x = x, y = 272 }, - scale = { x = 2, y = 2 }, + offset = { x = x, y = 3 }, + scale = { x = 3, y = 3 }, alignment = { x = 1, y = 1 }, z_index = 100, }) From 5c563d6ffd16ba6d64691fff5e0356b85eb4fe80 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 2 Aug 2021 12:24:34 +0000 Subject: [PATCH 053/111] Make eating particles much more MC like! --- mods/PLAYER/mcl_hunger/hunger.lua | 32 ++++++++++++------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index 5dec8b1b0..d9a6fd5fe 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -152,26 +152,18 @@ function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poiso -- If false, force item to not spawn any food partiles when eaten if def._food_particles ~= false and texture and texture ~= "" then local v = user:get_velocity() or user:get_player_velocity() - local minvel = vector.add(v, {x=-1, y=1, z=-1}) - local maxvel = vector.add(v, {x=1, y=2, z=1}) - - minetest.add_particlespawner({ - amount = math.min(math.max(8, hunger_change*2), 25), - time = 0.1, - minpos = {x=pos.x, y=pos.y, z=pos.z}, - maxpos = {x=pos.x, y=pos.y, z=pos.z}, - minvel = minvel, - maxvel = maxvel, - minacc = {x=0, y=-5, z=0}, - maxacc = {x=0, y=-9, z=0}, - minexptime = 1, - maxexptime = 1, - minsize = 1, - maxsize = 2, - collisiondetection = true, - vertical = false, - texture = texture, - }) + for i = 0, math.min(math.max(8, hunger_change*2), 25) do + minetest.add_particle({ + pos = { x = pos.x, y = pos.y, z = pos.z }, + velocity = vector.add(v, { x = math.random(-1, 1), y = math.random(1, 2), z = math.random(-1, 1) }), + acceleration = { x = 0, y = math.random(-9, -5), z = 0 }, + expirationtime = 1, + size = math.random(1, 2), + collisiondetection = true, + vertical = false, + texture = "[combine:3x3:" .. -i .. "," .. -i .. "=" .. texture, + }) + end end minetest.sound_play("mcl_hunger_bite", { max_hear_distance = 12, From df0c1f1dd1e32dc74a1b9e9a767037c517cdf071 Mon Sep 17 00:00:00 2001 From: Emily Date: Fri, 6 Aug 2021 11:14:17 +0200 Subject: [PATCH 054/111] Make bows and fishing rods show their durability in description (Fixes issue #1773) --- mods/HELP/mcl_tt/snippets_mcl.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 3c79f52e8..121d8ed70 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -107,3 +107,8 @@ tt.register_snippet(function(itemstring) end end) +tt.register_snippet(function(itemstring, _, itemstack) + if itemstring:sub(1, 23) == "mcl_fishing:fishing_rod" or itemstring:sub(1, 12) == "mcl_bows:bow" then + return S("Durability: @1 uses", mcl_util.calculate_durability(itemstack or ItemStack(itemstring))) + end +end) From 5bb57a81ad46c163b58da046920b8a4bee18b30b Mon Sep 17 00:00:00 2001 From: Emily Date: Fri, 6 Aug 2021 11:55:27 +0200 Subject: [PATCH 055/111] Add durability tooltip to translation template --- mods/HELP/mcl_tt/locale/template.txt | 1 + mods/HELP/mcl_tt/snippets_mcl.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/HELP/mcl_tt/locale/template.txt b/mods/HELP/mcl_tt/locale/template.txt index 1259216c7..6fb735b13 100644 --- a/mods/HELP/mcl_tt/locale/template.txt +++ b/mods/HELP/mcl_tt/locale/template.txt @@ -45,3 +45,4 @@ Mining durability: @1= Block breaking strength: @1= @1 uses= Unlimited uses= +Durability: @1= diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 121d8ed70..825776f5f 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -109,6 +109,6 @@ end) tt.register_snippet(function(itemstring, _, itemstack) if itemstring:sub(1, 23) == "mcl_fishing:fishing_rod" or itemstring:sub(1, 12) == "mcl_bows:bow" then - return S("Durability: @1 uses", mcl_util.calculate_durability(itemstack or ItemStack(itemstring))) + return S("Durability: @1", S("@1 uses", mcl_util.calculate_durability(itemstack or ItemStack(itemstring)))) end end) From 664c2381374ee25f423d2b0d0eb66b838257eca6 Mon Sep 17 00:00:00 2001 From: NO11 Date: Fri, 6 Aug 2021 10:52:55 +0000 Subject: [PATCH 056/111] Add german translation for the bow/fishing rod desc --- mods/HELP/mcl_tt/locale/mcl_tt.de.tr | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/HELP/mcl_tt/locale/mcl_tt.de.tr b/mods/HELP/mcl_tt/locale/mcl_tt.de.tr index 8f878afc7..54c376c3b 100644 --- a/mods/HELP/mcl_tt/locale/mcl_tt.de.tr +++ b/mods/HELP/mcl_tt/locale/mcl_tt.de.tr @@ -45,3 +45,4 @@ Mining durability: @1=Grabehaltbarkeit: @1 Block breaking strength: @1=Blockbruchstärke: @1 @1 uses=@1 Verwendungen Unlimited uses=Unbegrenzte Verwendungen +Durability: @1=Haltbarkeit: @1 From f8dcf056707c917f2b77aead6669ee0d05905c86 Mon Sep 17 00:00:00 2001 From: NO11 Date: Wed, 11 Aug 2021 15:41:45 +0000 Subject: [PATCH 057/111] Add MC like nodebox for anvils --- mods/ITEMS/mcl_anvils/init.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index fbf6fb751..51b78da6f 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -297,9 +297,10 @@ local anvildef = { node_box = { type = "fixed", fixed = { - {-8/16, 2/16, -5/16, 8/16, 8/16, 5/16}, -- top - {-5/16, -4/16, -2/16, 5/16, 5/16, 2/16}, -- middle - {-8/16, -8/16, -5/16, 8/16, -4/16, 5/16}, -- base + { -6/16, -8/16, -6/16, 6/16, -4/16, 6/16 }, + { -5/16, -4/16, -4/16, 5/16, -3/16, 4/16 }, + { -4/16, -3/16, -2/16, 4/16, 2/16, 2/16 }, + { -8/16, 2/16, -5/16, 8/16, 8/16, 5/16 }, } }, sounds = mcl_sounds.node_sound_metal_defaults(), From cb55c36863b429a8328c98bc478d525d081727ca Mon Sep 17 00:00:00 2001 From: NO11 Date: Wed, 11 Aug 2021 15:44:43 +0000 Subject: [PATCH 058/111] Correct the texture of anvils Because of the new node_nox, the textures have to be a little bit bigger. --- .../mcl_anvils_anvil_top_damaged_0.png | Bin 195 -> 6074 bytes .../mcl_anvils_anvil_top_damaged_1.png | Bin 209 -> 5855 bytes .../mcl_anvils_anvil_top_damaged_2.png | Bin 220 -> 5882 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_0.png b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_0.png index 84c64e9159abbd2703d701a32211caa4cc9b8418..43938aa7265afa58d0394ae683e7815a6159dc40 100644 GIT binary patch literal 6074 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 O6RBikV7~v1h5rJhQRw{u delta 168 zcmV;Z09XIIFT(+lBYyxAP)t-s0000rH8njwJxNJPCMG5_g{t@2{xwnxfY!o1m=5Hpkx&&VMYdA3f<* zke78TURM65f7Q&E)6%q1(c%DjCf&CglDtjw&Pyg17tXM5Xa4ki$W+k}+Y+apP1z&a(J1~8He2!hrX@5T9>9(DYWq)wO zmXCRDm7WOQ&aQtf^mvbixr}V*-pJLw2(GW->sQ@xep+U6HF3Gkw#-Med?u_RFg_rVKp2K{wOpwbzKyg3}j% zXw!T990s$TT%$;Kk8=X>p*pWt+18=cXGER;7lr=k{A@ z*ANyWaJqD6iVcn?O{Zvx9?rFL8?wsav;~Tv%~KvUXVM6LmSb)#RN+Ou=FO#IRwjB1_h! zdrg}0nq3uI_AB-w85yR1=nA^qCNBZF6=dn+Q~brub* zGoq4QTAqIS(3*oud05E^ne(jph69C?yj>xuuZ9dycyNyh&dBs!_bL%^pC=7@MHE!$ z`;RS1A%(v9{zUGbhY8UMhtDt%ygGCn`>X9jd(DH*u@O(R6nX1xZ^$3TL`0 zMP~ioU-ehk_L-A?yTL|XLwUaW+?8#m7fMQ2Y#ofb?RXck?b4-;;c;W}gq7P@Ca%{1 zc-?H+L%{)A$-D=n9+uh9^B}+eGfR;3Dq-i`kuM8XEBc<=H=i+gchvEUKMqOf{LAey zJ>zENvWxFCF1}l9mf`WDlzMZ`vpG?fP5YVmCbhd2$fj=R>^-(7@uvHf-#HJqXTD!N z`1-jmF1K%0n!0LCi~RTJU?nZ%TAFqo*3%qvczFW0TyWshU5vSHJARRS3ROr0ZB^Lllsi?1Sn9$ev zLE+rCrURm!gs zms`&aiOP1+tMzjh(E{7bH8<{YF8i-FU+)M(+Y|J5`=XzSOO{PNAGUPsQrGkyla6I+ zqVF9&J9Ss>)YkQFsmVtVWjFFKG4#0`vra=anw^50NCcEkDrh2!QjE}a3Kd`o z&#^j{2%e1)WHBN`F#+XS>2V4fl?W(P*ujiol`j&D2F}Hih`Aw=@Z8xjPeK{%W#y^k z>l7*lLWsyZg&b4!bpnb}myfCWhHg5AY=jWA1(fLEFtV=_N60K1i^ib(>(F?J;$=nl z#3fRGxZn6r30xu-P+|!}#i!G?S}je>q$zP39pv$NbOuC+ASy1AQq>62rCtIok&FoX$-nT(SxBT{Nq36`z%8pnV>@G;fPwP z!C}Nd9>ECL?nza0jkaiZfh|z-X@;Zg8OTP#DqhCg_(O15o64n@! z3jG8W!+iM?C5%e=#-ALJ%j6*(HdP8SK`M*I^`P>kVh)wVg&~9oa+q8RvzwFi^^p&xl|U{gG1#ZA|90`mT)|zJRXzF+4(gvekU=mBv(cx;YwW*$&CeiVYMQ6*+j1sOC5GSVe5 zf4mY`hzJ1%RfuE=U4_Yv1BQ(;EC;~|k>PX*D4?-lr%>^IaYRHY@kpgoE}$4@OEyRv z4;9(7^SJPXl(3O#1S1l|iR(ObJ|Y?2*z`1>C4b%L!T+Tc5v$Z<|DVn$XqSpNPH2_* z>`**Z9EZTfmvue|?otXzWT=|J6NG=WsQES?7_79&(x!r)R_Y#5@7UoT>(ZKK6!(1gyy)002NQLKy7d>w#q-TNifa9@7W_0OEvx z-jSBqT`Er6n1Ysmlj4#!x%)SzaDO1L-UaBbs=cRct&4|ev;%}A0Rma`<6kW*+O_w3 z@+>ay?G!GKt4RsnpMOXCW|is8`UkGVZ|ydJvn_vglHU7z!Ut$@-TI$bj_}&tx0C_4 akwUgRUaj0-vC;5ngU~<3Z@15^lz#)4DYXCq delta 163 zcmV;U09^myEztpxBL)B%P)t-slm8VMe;sF9xBvhE0d!JMQvg8b*k%9#0B1==K~#7F z9m~ND0zn8yVRmd_SutKmw*g}ZBrp|#Q-K{g{Tu$8}E3 za0gU)FPMq~VeUxoV_~1)8Mu6f0uhP5d4|=ssf}NuvD_28@-6qm<9r^S{_@Ka5oW~6 RhyMTo002ovPDHLkV1mc^K{fyY diff --git a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_2.png b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_2.png index 5f5cfbffa6f0ebd6c1fa06ad201cb312ca6875e0..096f65eac2203e52431aebcd73c473f68a690441 100644 GIT binary patch literal 5882 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 ByH@}J delta 171 zcmV;c0960_E!+W+BL)B)P)t-slM5Cbe{A6T_y7O^0d!JMQvg8b*k%9#0B=b|K~#7F zV_;xZHWCt6U|?Wiatuo=0Wp|GDl*&+Kn#!eaEM4nNO_3>h~Zu$=mKU4I*Nybr5xQW z(!tux(!*LIx-v>azzmo0a!0U~dwGc Date: Fri, 13 Aug 2021 11:35:18 +0200 Subject: [PATCH 059/111] Update French translation (part 1) --- mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr | 5 +++-- .../mcl_minecarts/locale/mcl_minecarts.fr.tr | 1 + mods/ENTITIES/mobs_mc/locale/template.txt | 1 + mods/HELP/doc/doc_items/locale/doc_items.fr.tr | 2 +- mods/HUD/mcl_credits/locale/mcl_credits.de.tr | 1 + mods/HUD/mcl_credits/locale/mcl_credits.es.tr | 14 ++++++++++++++ mods/HUD/mcl_credits/locale/mcl_credits.fr.tr | 14 ++++++++++++++ mods/HUD/mcl_credits/locale/mcl_credits.pl.tr | 14 ++++++++++++++ mods/HUD/mcl_credits/locale/mcl_credits.ru.tr | 14 ++++++++++++++ mods/ITEMS/mcl_chests/init.lua | 2 +- mods/ITEMS/mcl_chests/locale/template.txt | 2 +- .../ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr | 3 +++ .../ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr | 3 +++ .../ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr | 3 +++ mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr | 5 ++++- 15 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 mods/HUD/mcl_credits/locale/mcl_credits.es.tr create mode 100644 mods/HUD/mcl_credits/locale/mcl_credits.fr.tr create mode 100644 mods/HUD/mcl_credits/locale/mcl_credits.pl.tr create mode 100644 mods/HUD/mcl_credits/locale/mcl_credits.ru.tr create mode 100644 mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr create mode 100644 mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr create mode 100644 mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr diff --git a/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr b/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr index 04d6d9da9..785d50146 100644 --- a/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr +++ b/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr @@ -6,6 +6,7 @@ Boats are used to travel on the surface of water.=Les bateaux sont utilisés pou Dark Oak Boat=Bateau en Chêne Noir Jungle Boat=Bateau en Acajou Oak Boat=Bateau en Chêne -Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Cliquez de nouveau avec le bouton droit sur le bateau pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet. +Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Utilisez [Sneak] pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet. Spruce Boat=Bateau en Sapin -Water vehicle=Véhicule aquatique \ No newline at end of file +Water vehicle=Véhicule aquatique +Sneak to dismount= \ No newline at end of file diff --git a/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr b/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr index 39cdfd013..67ed5eb1b 100644 --- a/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr +++ b/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr @@ -33,3 +33,4 @@ Activates minecarts when powered=Active les wagonnets lorsqu'il est alimenté Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé +Sneak to dismount= \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 04ba9e465..7b55c1b89 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -28,6 +28,7 @@ Pig= Polar Bear= Rabbit= Killer Bunny= +The Killer Bunny= Sheep= Shulker= Silverfish= diff --git a/mods/HELP/doc/doc_items/locale/doc_items.fr.tr b/mods/HELP/doc/doc_items/locale/doc_items.fr.tr index 5d655404d..824ceeeba 100644 --- a/mods/HELP/doc/doc_items/locale/doc_items.fr.tr +++ b/mods/HELP/doc/doc_items/locale/doc_items.fr.tr @@ -2,7 +2,7 @@ Using it as fuel turns it into: @1.=L'utiliser comme combustible le transforme en : @1. @1 seconds=@1 secondes # Item count times item name -%@1×@2=%@1×@ +@1×@2=@1×@ # Itemname (25%) @1 (@2%)=@1 (@2%) # Itemname (<0.5%) diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.de.tr b/mods/HUD/mcl_credits/locale/mcl_credits.de.tr index 6a38d18e6..fa26f5bc4 100644 --- a/mods/HUD/mcl_credits/locale/mcl_credits.de.tr +++ b/mods/HUD/mcl_credits/locale/mcl_credits.de.tr @@ -7,6 +7,7 @@ Creator of MineClone2=Schöpfer von MineClone2 Developers=Entwickler Jump to speed up (additionally sprint)=Springen, um zu beschleunigen (zusätzlich sprinten) Maintainers=Betreuer +MineClone5=MineClone5 Original Mod Authors=Original-Mod-Autoren Sneak to skip=Schleichen zum Überspringen Textures=Texturen diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.es.tr b/mods/HUD/mcl_credits/locale/mcl_credits.es.tr new file mode 100644 index 000000000..a8886286e --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.es.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models= +A faithful Open Source clone of Minecraft= +Contributors= +Creator of MineClone= +Creator of MineClone2= +Developers= +Jump to speed up (additionally sprint)= +Maintainers= +MineClone5= +Original Mod Authors= +Sneak to skip= +Textures= +Translations= \ No newline at end of file diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.fr.tr b/mods/HUD/mcl_credits/locale/mcl_credits.fr.tr new file mode 100644 index 000000000..b34249eff --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.fr.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models=Modèles 3D +A faithful Open Source clone of Minecraft=Un clone open source de Minecraft +Contributors=Contributeurs +Creator of MineClone=Créateur de MineClone +Creator of MineClone2=Créateur de MineClone2 +Developers=Développeurs +Jump to speed up (additionally sprint)=Saut pour accélérer (peut être combiné avec sprint) +Maintainers=Mainteneurs +MineClone5=MineClone5 +Original Mod Authors=Auteurs des mods originaux +Sneak to skip=Shift pour passer +Textures=Textures +Translations=Traductions \ No newline at end of file diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.pl.tr b/mods/HUD/mcl_credits/locale/mcl_credits.pl.tr new file mode 100644 index 000000000..a8886286e --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.pl.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models= +A faithful Open Source clone of Minecraft= +Contributors= +Creator of MineClone= +Creator of MineClone2= +Developers= +Jump to speed up (additionally sprint)= +Maintainers= +MineClone5= +Original Mod Authors= +Sneak to skip= +Textures= +Translations= \ No newline at end of file diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.ru.tr b/mods/HUD/mcl_credits/locale/mcl_credits.ru.tr new file mode 100644 index 000000000..a8886286e --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.ru.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models= +A faithful Open Source clone of Minecraft= +Contributors= +Creator of MineClone= +Creator of MineClone2= +Developers= +Jump to speed up (additionally sprint)= +Maintainers= +MineClone5= +Original Mod Authors= +Sneak to skip= +Textures= +Translations= \ No newline at end of file diff --git a/mods/ITEMS/mcl_chests/init.lua b/mods/ITEMS/mcl_chests/init.lua index cd66c3fc4..69f6a601d 100644 --- a/mods/ITEMS/mcl_chests/init.lua +++ b/mods/ITEMS/mcl_chests/init.lua @@ -1133,7 +1133,7 @@ for color, desc in pairs(boxtypes) do if mod_doc then if is_canonical then longdesc = S("A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors.") - usagehelp = S("To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out.") + usagehelp = S("To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents.") entry_name = S("Shulker Box") else create_entry = false diff --git a/mods/ITEMS/mcl_chests/locale/template.txt b/mods/ITEMS/mcl_chests/locale/template.txt index 1d947184b..d680c24c9 100644 --- a/mods/ITEMS/mcl_chests/locale/template.txt +++ b/mods/ITEMS/mcl_chests/locale/template.txt @@ -24,7 +24,7 @@ Red Shulker Box= Grey Shulker Box= Black Shulker Box= A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors.= -To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out.= +To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents.= Shulker Box= Large Chest= Inventory= diff --git a/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr new file mode 100644 index 000000000..e66eb06a5 --- /dev/null +++ b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_fireworks +Firework Rocket= +Flight Duration:= \ No newline at end of file diff --git a/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr new file mode 100644 index 000000000..b02faa428 --- /dev/null +++ b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_fireworks +Firework Rocket=Fusée +Flight Duration:=Durée de vol : \ No newline at end of file diff --git a/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr new file mode 100644 index 000000000..e66eb06a5 --- /dev/null +++ b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_fireworks +Firework Rocket= +Flight Duration:= \ No newline at end of file diff --git a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr index 9ef7cd5c5..1808e839d 100644 --- a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr +++ b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr @@ -1,5 +1,8 @@ # textdomain: mcl_maps Empty Map=Carte Vierge Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Les cartes vierges ne sont pas utiles en tant que cartes, mais elles peuvent être empilées et transformées en cartes utilisables. -Rightclick to start using the map (which can't be stacked anymore).=Clic droit pour commencer à utiliser la carte (qui ne peut plus être empilée). +Rightclick to create a filled map (which can't be stacked anymore).=Clic droit pour créer une carte remplie (qui ne peut plus être empilée). Map=Carte +Shows a map image.=Affiche une carte. +When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Lors de sa création, la carte sauvegarde le terrain proche sous forme d'image qui peut être consultée n'importe quand en tenant la carte dans la main. +Hold the map in your hand. This will display a map on your screen.=Tenez la carte dans votre main. Cela affichera la carte à l'écran. From 58a292a4f3edcf6816936b89a6b32275fb785299 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 16 Aug 2021 13:48:08 +0200 Subject: [PATCH 060/111] fix inconsistency --- mods/HUD/mcl_title/init.lua | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index d1dbece4b..ffdc45639 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -36,7 +36,11 @@ local string = string local pairs = pairs local function gametick_to_secondes(gametick) - return gametick / 20 + if gametick then + return gametick / 20 + else + return nil + end end @@ -46,9 +50,9 @@ local player_params = {} minetest.register_on_joinplayer(function(player) local playername = player:get_player_name() player_params[player] = { - stay = gametick_to_secondes(mcl_title.defaults.stay), - --fadeIn = gametick_to_secondes(mcl_title.defaults.fadein), - --fadeOut = gametick_to_secondes(mcl_title.defaults.fadeout), + stay = mcl_title.defaults.stay, + --fadeIn = mcl_title.defaults.fadein, + --fadeOut = mcl_title.defaults.fadeout, } local _, hex_color = get_color("white") huds_idx.title[player] = player:hud_add({ @@ -106,9 +110,9 @@ end) function mcl_title.params_set(player, data) player_params[player] = { - stay = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.defaults.stay), - --fadeIn = gametick_to_secondes(data.fadeIn) or gametick_to_secondes(mcl_title.defaults.fadein), - --fadeOut = gametick_to_secondes(data.fadeOut) or gametick_to_secondes(mcl_title.defaults.fadeout), + stay = data.stay or mcl_title.defaults.stay, + --fadeIn = data.fadeIn or mcl_title.defaults.fadein, + --fadeOut = data.fadeOut or mcl_title.defaults.fadeout, } end @@ -134,7 +138,7 @@ function mcl_title.set(player, type, data) player:hud_change(huds_idx[type][player], "text", data.text) player:hud_change(huds_idx[type][player], "number", hex_color) - hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or mcl_title.params_get(player).stay + hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.params_get(player).stay) return true end From 40898d3e9dfeb492ecaca2621308c8c125ef5471 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 16 Aug 2021 14:19:50 +0200 Subject: [PATCH 061/111] WIP bold and italic support --- mods/HUD/mcl_title/init.lua | 38 +++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index ffdc45639..933158d20 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -43,6 +43,23 @@ local function gametick_to_secondes(gametick) end end +--https://github.com/minetest/minetest/blob/b3b075ea02034306256b486dd45410aa765f035a/doc/lua_api.txt#L8477 + +local function style_to_bits(bold, italic) + if bold then + if italic then + return 3 + else + return 1 + end + else + if italic then + return 2 + else + return 0 + end + end +end --PARAMS SYSTEM local player_params = {} @@ -60,8 +77,7 @@ minetest.register_on_joinplayer(function(player) position = mcl_title.layout.title.position, alignment = mcl_title.layout.title.alignment, text = "", - --bold = data.bold, - --italic = data.italic, + style = 0, size = {x = mcl_title.layout.title.size}, number = hex_color, z_index = 100, @@ -71,8 +87,7 @@ minetest.register_on_joinplayer(function(player) position = mcl_title.layout.subtitle.position, alignment = mcl_title.layout.subtitle.alignment, text = "", - --bold = data.bold, - --italic = data.italic, + style = 0, size = {x = mcl_title.layout.subtitle.size}, number = hex_color, z_index = 100, @@ -82,8 +97,7 @@ minetest.register_on_joinplayer(function(player) position = mcl_title.layout.actionbar.position, offset = {x = 0, y = -210}, alignment = mcl_title.layout.actionbar.alignment, - --bold = data.bold, - --italic = data.italic, + style = 0, text = "", size = {x = mcl_title.layout.actionbar.size}, number = hex_color, @@ -131,13 +145,12 @@ function mcl_title.set(player, type, data) return false end - --TODO: enable this code then Fleckenstein's pr get merged (in about 5-6 years lol) - - --if data.bold == nil then data.bold = false end - --if data.italic == nil then data.italic = false end - player:hud_change(huds_idx[type][player], "text", data.text) player:hud_change(huds_idx[type][player], "number", hex_color) + + --apply bold and italic + player:hud_change(huds_idx[type][player], "style", style_to_bits(data.bold, data.italic)) + hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.params_get(player).stay) return true end @@ -145,6 +158,7 @@ end function mcl_title.remove(player, type) if player then player:hud_change(huds_idx[type][player], "text", "") + player:hud_change(huds_idx[type][player], "style", 0) --no styling end end @@ -184,7 +198,7 @@ end) minetest.register_chatcommand("title", { func = function(name, param) local player = minetest.get_player_by_name(name) - mcl_title.set(player, "title", {text=param, color="gold"}) + mcl_title.set(player, "title", {text=param, color="gold", bold=true, italic=true}) end, }) From df4b8e64cc153ba70457a199661e1e6e92e30bf9 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Thu, 19 Aug 2021 19:21:33 +0200 Subject: [PATCH 062/111] finish `mcl_title` API + doc --- mods/HUD/mcl_title/API.md | 8 ++++++ mods/HUD/mcl_title/init.lua | 28 +++++++++++--------- mods/HUD/mcl_tmp_message/API.md | 7 ----- mods/HUD/mcl_tmp_message/init.lua | 44 ------------------------------- mods/HUD/mcl_tmp_message/mod.conf | 3 --- 5 files changed, 23 insertions(+), 67 deletions(-) delete mode 100644 mods/HUD/mcl_tmp_message/API.md delete mode 100644 mods/HUD/mcl_tmp_message/init.lua delete mode 100644 mods/HUD/mcl_tmp_message/mod.conf diff --git a/mods/HUD/mcl_title/API.md b/mods/HUD/mcl_title/API.md index 50614be4f..97d75ece8 100644 --- a/mods/HUD/mcl_title/API.md +++ b/mods/HUD/mcl_title/API.md @@ -39,4 +39,12 @@ Allow mods to set `stay` and upcomming `fadeIn`/`fadeOut` params. ```lua mcl_title.params_set(player, {stay = 600}) --elements with no 'data.stay' field will stay during 30s (600/20) +``` + +## mcl_title.params_get(player) + +Get `stay` and upcomming `fadeIn` and `fadeOut` params of a player as a table. + +```lua +mcl_title.params_get(player) ``` \ No newline at end of file diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 933158d20..2ea1571c8 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -32,7 +32,7 @@ mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y local get_color = mcl_util.get_color -local string = string +--local string = string local pairs = pairs local function gametick_to_secondes(gametick) @@ -44,7 +44,7 @@ local function gametick_to_secondes(gametick) end --https://github.com/minetest/minetest/blob/b3b075ea02034306256b486dd45410aa765f035a/doc/lua_api.txt#L8477 - +--[[ local function style_to_bits(bold, italic) if bold then if italic then @@ -60,24 +60,25 @@ local function style_to_bits(bold, italic) end end end +]] --PARAMS SYSTEM local player_params = {} minetest.register_on_joinplayer(function(player) - local playername = player:get_player_name() + --local playername = player:get_player_name() player_params[player] = { stay = mcl_title.defaults.stay, --fadeIn = mcl_title.defaults.fadein, --fadeOut = mcl_title.defaults.fadeout, } - local _, hex_color = get_color("white") + local _, hex_color = get_color("white") huds_idx.title[player] = player:hud_add({ hud_elem_type = "text", position = mcl_title.layout.title.position, alignment = mcl_title.layout.title.alignment, text = "", - style = 0, + --style = 0, size = {x = mcl_title.layout.title.size}, number = hex_color, z_index = 100, @@ -87,7 +88,7 @@ minetest.register_on_joinplayer(function(player) position = mcl_title.layout.subtitle.position, alignment = mcl_title.layout.subtitle.alignment, text = "", - style = 0, + --style = 0, size = {x = mcl_title.layout.subtitle.size}, number = hex_color, z_index = 100, @@ -97,7 +98,7 @@ minetest.register_on_joinplayer(function(player) position = mcl_title.layout.actionbar.position, offset = {x = 0, y = -210}, alignment = mcl_title.layout.actionbar.alignment, - style = 0, + --style = 0, text = "", size = {x = mcl_title.layout.actionbar.size}, number = hex_color, @@ -116,7 +117,7 @@ minetest.register_on_leaveplayer(function(player) huds_idx.subtitle[player] = nil huds_idx.actionbar[player] = nil - --remove timers form list + --remove timers from list hud_hide_timeouts.title[playername] = nil hud_hide_timeouts.subtitle[playername] = nil hud_hide_timeouts.actionbar[playername] = nil @@ -149,7 +150,7 @@ function mcl_title.set(player, type, data) player:hud_change(huds_idx[type][player], "number", hex_color) --apply bold and italic - player:hud_change(huds_idx[type][player], "style", style_to_bits(data.bold, data.italic)) + --player:hud_change(huds_idx[type][player], "style", style_to_bits(data.bold, data.italic)) hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.params_get(player).stay) return true @@ -158,7 +159,7 @@ end function mcl_title.remove(player, type) if player then player:hud_change(huds_idx[type][player], "text", "") - player:hud_change(huds_idx[type][player], "style", 0) --no styling + --player:hud_change(huds_idx[type][player], "style", 0) --no styling end end @@ -193,8 +194,8 @@ minetest.register_globalstep(function(dtime) end) ---TEMP STUFF!! ---TODO: remove then testing/tweaking done +--DEBUG STUFF!! +--[[ minetest.register_chatcommand("title", { func = function(name, param) local player = minetest.get_player_by_name(name) @@ -231,4 +232,5 @@ minetest.register_chatcommand("all", { mcl_title.set(player, "subtitle", {text=param, color="gold"}) mcl_title.set(player, "actionbar", {text=param, color="gold"}) end, -}) \ No newline at end of file +}) +]] \ No newline at end of file diff --git a/mods/HUD/mcl_tmp_message/API.md b/mods/HUD/mcl_tmp_message/API.md deleted file mode 100644 index 0a3fc06a3..000000000 --- a/mods/HUD/mcl_tmp_message/API.md +++ /dev/null @@ -1,7 +0,0 @@ -# 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 diff --git a/mods/HUD/mcl_tmp_message/init.lua b/mods/HUD/mcl_tmp_message/init.lua deleted file mode 100644 index 1456cd592..000000000 --- a/mods/HUD/mcl_tmp_message/init.lua +++ /dev/null @@ -1,44 +0,0 @@ -mcl_tmp_message = {} - -local huds = {} -local hud_hide_timeouts = {} - -function mcl_tmp_message.message(player, message) - local name = player:get_player_name() - player:hud_change(huds[name], "text", message) - hud_hide_timeouts[name] = 3 -end - -minetest.register_on_joinplayer(function(player) - huds[player:get_player_name()] = player:hud_add({ - hud_elem_type = "text", - position = {x=0.5, y=1}, - offset = {x = 0, y = -210}, - alignment = {x=0, y=0}, - number = 0xFFFFFF , - text = "", - z_index = 100, - }) -end) - -minetest.register_on_leaveplayer(function(player) - local name = player:get_player_name() - huds[name] = nil - hud_hide_timeouts[name] = nil -end) - -minetest.register_globalstep(function(dtime) - local new_timeouts = {} - for name, timeout in pairs(hud_hide_timeouts) do - timeout = timeout - dtime - if timeout <= 0 then - local player = minetest.get_player_by_name(name) - if player then - player:hud_change(huds[name], "text", "") - end - else - new_timeouts[name] = timeout - end - end - hud_hide_timeouts = new_timeouts -end) diff --git a/mods/HUD/mcl_tmp_message/mod.conf b/mods/HUD/mcl_tmp_message/mod.conf deleted file mode 100644 index ad453643e..000000000 --- a/mods/HUD/mcl_tmp_message/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = mcl_tmp_message -author = Fleckenstein -description = A simple API to show a temporary message to a player From af8e88f44cad6465e91530b0f87e8588e885cff3 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Tue, 24 Aug 2021 08:25:42 +0200 Subject: [PATCH 063/111] fix error in `mcl_title` documentation --- mods/HUD/mcl_title/API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/HUD/mcl_title/API.md b/mods/HUD/mcl_title/API.md index 97d75ece8..37f1c279f 100644 --- a/mods/HUD/mcl_title/API.md +++ b/mods/HUD/mcl_title/API.md @@ -21,7 +21,7 @@ mcl_title.set(player, "subtitle", {text="dummy subtitle", color="#612D2D"}) mcl_title.set(player, "subtitle", {text="dummy actionbar", color="red"}) --show a title in the HUD with minecraft color "gold" staying for 3 seconds (override stay setting) -mcl_title.set(player, "title", {text="dummy text", color="gold", stay=3}) +mcl_title.set(player, "title", {text="dummy text", color="gold", stay=60}) ``` ## mcl_title.remove(player, type) From f0af15fcd8006a66ce91ba3efbf77c24a8e8ffca Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 26 Aug 2021 10:14:57 +0000 Subject: [PATCH 064/111] Make anvil selection/collision box more MC like --- mods/ITEMS/mcl_anvils/init.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index 51b78da6f..e1685c60e 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -284,6 +284,12 @@ local function damage_anvil_by_falling(pos, distance) end end +local anvilbox = { + type = "fixed", + fixed = { + { -8 / 16, -8 / 16, -6 / 16, 8 / 16, 8 / 16, 6 / 16 }, + }, +} local anvildef = { groups = {pickaxey=1, falling_node=1, falling_node_damage=1, crush_after_fall=1, deco_block=1, anvil=1}, tiles = {"mcl_anvils_anvil_top_damaged_0.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"}, @@ -297,12 +303,14 @@ local anvildef = { node_box = { type = "fixed", fixed = { - { -6/16, -8/16, -6/16, 6/16, -4/16, 6/16 }, - { -5/16, -4/16, -4/16, 5/16, -3/16, 4/16 }, - { -4/16, -3/16, -2/16, 4/16, 2/16, 2/16 }, - { -8/16, 2/16, -5/16, 8/16, 8/16, 5/16 }, + { -6 / 16, -8 / 16, -6 / 16, 6 / 16, -4 / 16, 6 / 16 }, + { -5 / 16, -4 / 16, -4 / 16, 5 / 16, -3 / 16, 4 / 16 }, + { -4 / 16, -3 / 16, -2 / 16, 4 / 16, 2 / 16, 2 / 16 }, + { -8 / 16, 2 / 16, -5 / 16, 8 / 16, 8 / 16, 5 / 16 }, } }, + selection_box = anvilbox, + collision_box = anvilbox, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 1200, _mcl_hardness = 5, From ca086109bf17787e3a7b075ceb07ccb82810a3bb Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 31 Aug 2021 21:04:57 +0000 Subject: [PATCH 065/111] support tables for `_repair_material` --- mods/ITEMS/mcl_anvils/init.lua | 44 +++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index e1685c60e..d3b32b844 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -53,6 +53,15 @@ local function get_consumed_materials(tool, material) return materials_used end +local function contains(table, value) + for _, i in pairs(table) do + if i == value then + return true + end + end + return false +end + -- Given 2 input stacks, tells you which is the tool and which is the material. -- Returns ("tool", input1, input2) if input1 is tool and input2 is material. -- Returns ("material", input2, input1) if input1 is material and input2 is tool. @@ -60,9 +69,15 @@ end local function distinguish_tool_and_material(input1, input2) local def1 = input1:get_definition() local def2 = input2:get_definition() - if def1.type == "tool" and def1._repair_material then + local r1 = def1._repair_material + local r2 = def2._repair_material + if def1.type == "tool" and r1 and type(r1) == "table" and contains(r1, input2) then return "tool", input1, input2 - elseif def2.type == "tool" and def2._repair_material then + elseif def2.type == "tool" and r2 and type(r2) == "table" and contains(r2, input1) then + return "material", input2, input1 + elseif def1.type == "tool" and r1 then + return "tool", input1, input2 + elseif def2.type == "tool" and r2 then return "material", input2, input1 else return nil @@ -121,11 +136,28 @@ local function update_anvil_slots(meta) local distinguished, tool, material = distinguish_tool_and_material(input1, input2) if distinguished then local tooldef = tool:get_definition() + local repair = tooldef._repair_material local has_correct_material = false - if string.sub(tooldef._repair_material, 1, 6) == "group:" then - has_correct_material = minetest.get_item_group(material:get_name(), string.sub(tooldef._repair_material, 7)) ~= 0 - elseif material:get_name() == tooldef._repair_material then - has_correct_material = true + local material_name = material:get_name() + if type(repair) == "string" then + if string.sub(repair, 1, 6) == "group:" then + has_correct_material = minetest.get_item_group(material_name, string.sub(repair, 7)) ~= 0 + elseif material_name == repair then + has_correct_material = true + end + else + if contains(repair, material_name) then + has_correct_material = true + else + for _, r in pairs(repair) do + if string.sub(r, 1, 6) == "group:" then + if minetest.get_item_group(material_name, string.sub(r, 7)) ~= 0 then + has_correct_material = true + end + + end + end + end end if has_correct_material and tool:get_wear() > 0 then local materials_used = get_consumed_materials(tool, material) From 0da7b3fbda988d11ee79a03ca3c2719d6906e20f Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 2 Sep 2021 20:38:01 +0000 Subject: [PATCH 066/111] Make cactus mechanisms more MC like (Fix #1741) --- mods/ITEMS/mcl_core/functions.lua | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index eceb81c51..af4821c90 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -184,6 +184,7 @@ minetest.register_abm({ end, }) +-- Cactus mechanisms minetest.register_abm({ label = "Cactus growth", nodenames = {"mcl_core:cactus"}, @@ -195,19 +196,31 @@ minetest.register_abm({ end, }) --- Make cactus destroy items minetest.register_abm({ label = "Cactus destroy items", nodenames = {"mcl_core:cactus"}, interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - for _,object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do + for _, object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do local entity = object:get_luaentity() if entity and entity.name == "__builtin:item" then object:remove() end end + local posses = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } } + for _, p in pairs(posses) do + if minetest.registered_nodes[minetest.get_node(vector.new(pos.x + p[1], pos.y, pos.z + p[2])).name].walkable then + local posy = pos.y + while minetest.get_node(vector.new(pos.x, posy, pos.z)).name == "mcl_core:cactus" do + local pos = vector.new(pos.x, posy, pos.z) + minetest.remove_node(pos) + minetest.add_item(vector.offset(pos, math.random(-0.5, 0.5), 0, math.random(-0.5, 0.5)), "mcl_core:cactus") + posy = posy + 1 + end + break + end + end end, }) From bf62eb33fa97cc345fcab2515b2360cd18b80fbf Mon Sep 17 00:00:00 2001 From: NO11 Date: Fri, 3 Sep 2021 14:06:21 +0000 Subject: [PATCH 067/111] Change label of cactus abm --- mods/ITEMS/mcl_core/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index af4821c90..2ef73af72 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -197,7 +197,7 @@ minetest.register_abm({ }) minetest.register_abm({ - label = "Cactus destroy items", + label = "Cactus mechanisms", nodenames = {"mcl_core:cactus"}, interval = 1, chance = 1, From 5fedd914fb110aa8adeed1c3fe633a2c9e25c9e7 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 4 Sep 2021 19:14:08 +0000 Subject: [PATCH 068/111] Fix strange behaviour when filling end portal with bedrock inside (#1749) --- mods/ITEMS/mcl_portals/portal_end.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index 9f0db352a..e4982c39b 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -391,7 +391,3 @@ minetest.override_item("mcl_end:ender_eye", { return itemstack end, }) -minetest.override_item("mcl_core:bedrock", { - after_destruct = destroy_portal, -}) - From f41cea71fd61473090cd04ac8f206f56b9cd3410 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 6 Sep 2021 13:30:08 +0000 Subject: [PATCH 069/111] Make it possible to use shears in the dispenser for mobs (Fix #1233) --- mods/ITEMS/REDSTONE/mcl_dispensers/init.lua | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua index 7c2c07393..62ed2dc71 100644 --- a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua @@ -168,6 +168,59 @@ local dispenserdef = { end inv:set_stack("main", stack_id, stack) + + -- Use shears on sheeps + elseif igroups.shears then + for _, obj in pairs(minetest.get_objects_inside_radius(droppos, 1)) do + local entity = obj:get_luaentity() + if entity and not entity.child and not entity.gotten then + local entname = entity.name + local pos = obj:get_pos() + local used, texture = false + if entname == "mobs_mc:sheep" then + minetest.add_item(pos, entity.drops[2].name .. " " .. math.random(1, 3)) + if not entity.color then + entity.color = "unicolor_white" + end + entity.base_texture = { "blank.png", "mobs_mc_sheep.png" } + texture = entity.base_texture + entity.drops = { + { name = mobs_mc.items.mutton_raw, chance = 1, min = 1, max = 2 }, + } + used = true + elseif entname == "mobs_mc:snowman" then + texture = { + "mobs_mc_snowman.png", + "blank.png", "blank.png", + "blank.png", "blank.png", + "blank.png", "blank.png", + } + used = true + elseif entname == "mobs_mc:mooshroom" then + local droppos = vector.offset(pos, 0, 1.4, 0) + if entity.base_texture[1] == "mobs_mc_mooshroom_brown.png" then + minetest.add_item(droppos, mobs_mc.items.mushroom_brown .. " 5") + else + minetest.add_item(droppos, mobs_mc.items.mushroom_red .. " 5") + end + local oldyaw = obj:get_yaw() + obj:remove() + local cow = minetest.add_entity(pos, "mobs_mc:cow") + cow:set_yaw(oldyaw) + obj = cow + entity = cow:get_luaentity() + used = true + end + if used then + obj:set_properties({ textures = texture }) + entity.gotten = true + minetest.sound_play("mcl_tools_shears_cut", { pos = pos }, true) + stack:add_wear(65535 / stackdef._mcl_diggroups.shearsy.uses) + inv:set_stack("main", stack_id, stack) + end + end + end + -- Spawn Egg elseif igroups.spawn_egg then -- Spawn mob From dc8436fdf95afe224437d5fa6e3c883fa322f2a6 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 6 Sep 2021 14:34:25 +0000 Subject: [PATCH 070/111] Destroy objects near cactus faster (make it possible to throw items at a cactus) --- mods/ENTITIES/mcl_item_entity/init.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index ab1ac5752..7869b9d79 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -575,7 +575,7 @@ minetest.register_entity(":__builtin:item", { return true end, - on_step = function(self, dtime) + on_step = function(self, dtime, moveresult) if self._removed then self.object:set_properties({ physical = false @@ -642,6 +642,18 @@ minetest.register_entity(":__builtin:item", { end end + -- Destroy item when it collides with a cactus + if moveresult and moveresult.collides then + for _, collision in pairs(moveresult.collisions) do + local pos = collision.node_pos + if collision.type == "node" and minetest.get_node(pos).name == "mcl_core:cactus" then + self._removed = true + self.object:remove() + return + end + end + end + -- Push item out when stuck inside solid opaque node if def and def.walkable and def.groups and def.groups.opaque == 1 then local shootdir From 1a5339e907c1b5d572e2fe38a8b4451bf9bfff43 Mon Sep 17 00:00:00 2001 From: NO11 Date: Wed, 8 Sep 2021 14:22:53 +0000 Subject: [PATCH 071/111] Only use the shears once in dispenser if there are more mobs in front of the dispenser --- mods/ITEMS/REDSTONE/mcl_dispensers/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua index 62ed2dc71..82d53c806 100644 --- a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua @@ -217,6 +217,7 @@ local dispenserdef = { minetest.sound_play("mcl_tools_shears_cut", { pos = pos }, true) stack:add_wear(65535 / stackdef._mcl_diggroups.shearsy.uses) inv:set_stack("main", stack_id, stack) + break end end end From 89ff666a6a7a456daf22a224f42ba7a34919aeec Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 12 Sep 2021 12:21:18 +0000 Subject: [PATCH 072/111] Add playersSleepingPercentage server setting (Fix #920) --- mods/ITEMS/mcl_beds/functions.lua | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index e196f69ad..fd8a6d7cd 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -9,6 +9,7 @@ local weather_mod = minetest.get_modpath("mcl_weather") local explosions_mod = minetest.get_modpath("mcl_explosions") local spawn_mod = minetest.get_modpath("mcl_spawn") local worlds_mod = minetest.get_modpath("mcl_worlds") +local players_in_bed_setting = tonumber(minetest.settings:get("mcl_playersSleepingPercentage")) -- Helper functions @@ -34,19 +35,10 @@ local function is_night_skip_enabled() end local function check_in_beds(players) - local in_bed = mcl_beds.player if not players then players = minetest.get_connected_players() end - - for n, player in pairs(players) do - local name = player:get_player_name() - if not in_bed[name] then - return false - end - end - - return #players > 0 + return players_in_bed_setting <= (#mcl_beds.player * 100) / #players end -- These monsters do not prevent sleep @@ -198,8 +190,8 @@ end local function update_formspecs(finished, ges) local ges = ges or #minetest.get_connected_players() local form_n = "size[12,5;true]" - local all_in_bed = ges == player_in_bed - local night_skip = is_night_skip_enabled() + local all_in_bed = players_in_bed_setting <= (player_in_bed * 100) / ges + local night_skip = is_night_skip_enabled() and players_in_bed_setting <= 100 local button_leave = "button_exit[4,3;4,0.75;leave;"..F(S("Leave bed")).."]" local button_abort = "button_exit[4,3;4,0.75;leave;"..F(S("Abort sleep")).."]" local bg_presleep = "bgcolor[#00000080;true]" @@ -212,7 +204,7 @@ local function update_formspecs(finished, ges) return elseif not is_sp then local text = S("Players in bed: @1/@2", player_in_bed, ges) - if not night_skip then + if not night_skip or players_in_bed_setting > 100 then text = text .. "\n" .. S("Note: Night skip is disabled.") form_n = form_n .. bg_presleep form_n = form_n .. button_leave @@ -221,7 +213,13 @@ local function update_formspecs(finished, ges) form_n = form_n .. bg_sleep form_n = form_n .. button_abort else - text = text .. "\n" .. S("You will fall asleep when all players are in bed.") + local comment = "You will fall asleep when " + if players_in_bed_setting == 100 then + comment = comment .. "all players are in bed." + else + comment = comment .. players_in_bed_setting .. "% of all players are in bed." + end + text = text .. "\n" .. S(comment) form_n = form_n .. bg_presleep form_n = form_n .. button_leave end From 0bc9ab9233811b508e1aa29c4b1ea421b47fead3 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 12 Sep 2021 12:23:28 +0000 Subject: [PATCH 073/111] Add playersSleepingPercentage setting to settingtypes.txt --- settingtypes.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/settingtypes.txt b/settingtypes.txt index f605019ad..89e11833f 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -33,6 +33,11 @@ mcl_tnt_griefing (TNT destroys blocks) bool true # This setting is only read at startup. enable_bed_respawn (Respawn at bed) bool true +# How many players have to sleep to skip the night, in percent. +# Setting to 0 will mean 1 player is always enough to skip the night. Setting above 100 will prevent skipping the night. +# 100 by default. +mcl_playersSleepingPercentage (Players Sleeping Percentage) int 100 + # If enabled, the night can be skipped if all players are in bed. # This setting is only read at startup. enable_bed_night_skip (Skip night when sleeping) bool true From cd84c472dcb67b32b74397f87c00503b7414fc77 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 12 Sep 2021 12:49:39 +0000 Subject: [PATCH 074/111] Add translation support. --- mods/ITEMS/mcl_beds/functions.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index fd8a6d7cd..01ccec851 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -215,11 +215,11 @@ local function update_formspecs(finished, ges) else local comment = "You will fall asleep when " if players_in_bed_setting == 100 then - comment = comment .. "all players are in bed." + comment = S(comment .. "all players are in bed.") else - comment = comment .. players_in_bed_setting .. "% of all players are in bed." + comment = S(comment .. "@1% of all players are in bed.", players_in_bed_setting) end - text = text .. "\n" .. S(comment) + text = text .. "\n" .. comment form_n = form_n .. bg_presleep form_n = form_n .. button_leave end From 9f9799d96e699a0b64bce5fee061deeb040b3aa4 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 12 Sep 2021 12:50:54 +0000 Subject: [PATCH 075/111] Update template.txt in mcl_beds --- mods/ITEMS/mcl_beds/locale/template.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_beds/locale/template.txt b/mods/ITEMS/mcl_beds/locale/template.txt index 8301dfa33..5525bd91b 100644 --- a/mods/ITEMS/mcl_beds/locale/template.txt +++ b/mods/ITEMS/mcl_beds/locale/template.txt @@ -37,5 +37,6 @@ Players in bed: @1/@2= Note: Night skip is disabled.= You're sleeping.= You will fall asleep when all players are in bed.= +You will fall asleep when @1% of all players are in bed.= You're in bed.= Allows you to sleep= From 410b7c7844b674a062e1726a058e992698b9b34e Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 12 Sep 2021 12:52:26 +0000 Subject: [PATCH 076/111] Update german translation for mcl_beds --- mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr index 16592115e..eb6967941 100644 --- a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr +++ b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr @@ -37,5 +37,6 @@ Players in bed: @1/@2=Spieler im Bett: @1/@2 Note: Night skip is disabled.=Anmerkung: Überspringen der Nacht deaktiviert. You're sleeping.=Sie schlafen. You will fall asleep when all players are in bed.=Sie werden einschlafen, wenn alle Spieler im Bett sind. +You will fall asleep when @1% of all players are in bed.=Sie werden einschlafen, wenn @1% der Spieler im Bett sind. You're in bed.=Sie sind im Bett. Allows you to sleep=Zum Einschafen From 1c192f4fbbee2089ff72912cf369e8591fd4e481 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Thu, 8 Jul 2021 15:34:50 +0200 Subject: [PATCH 077/111] Do not send useless HUDCHANGE packets Several mods set or unset the visibility of a HUD bar way too often (e.g. in a globalstep handler), causing the server to send a lot of superfluous HUDCHANGE packets to each client. Returning from hb.hide_hudbar() early if HUD bar visibility would not change prevents sending these packets. --- mods/HUD/hudbars/init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/HUD/hudbars/init.lua b/mods/HUD/hudbars/init.lua index 08f1914ca..505ff403b 100644 --- a/mods/HUD/hudbars/init.lua +++ b/mods/HUD/hudbars/init.lua @@ -425,6 +425,7 @@ function hb.hide_hudbar(player, identifier) local name = player:get_player_name() local hudtable = hb.get_hudtable(identifier) if hudtable == nil then return false end + if hudtable.hudstate[name].hidden == true then return true end if hb.settings.bar_type == "progress_bar" then if hudtable.hudids[name].icon then player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0}) @@ -443,6 +444,7 @@ function hb.unhide_hudbar(player, identifier) local name = player:get_player_name() local hudtable = hb.get_hudtable(identifier) if hudtable == nil then return false end + if hudtable.hudstate[name].hidden == false then return true end local value = hudtable.hudstate[name].value local max = hudtable.hudstate[name].max if hb.settings.bar_type == "progress_bar" then From 95c4d6472bc57c056c5116be88d8f99550ec04b6 Mon Sep 17 00:00:00 2001 From: Nils Dagsson Moskopp Date: Sun, 4 Jul 2021 03:25:05 +0200 Subject: [PATCH 078/111] Send FOV packets only when necessary Before this change, about 10 to 30 FOV packets were sent from the server to each connected client each second. This patch only sends FOV packets when the FOV actually needs to be changed, i.e. when the player starts or stops sprinting. --- mods/PLAYER/mcl_sprint/init.lua | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mods/PLAYER/mcl_sprint/init.lua b/mods/PLAYER/mcl_sprint/init.lua index 73a518c42..4c0d609c9 100644 --- a/mods/PLAYER/mcl_sprint/init.lua +++ b/mods/PLAYER/mcl_sprint/init.lua @@ -69,18 +69,19 @@ local function setSprinting(playerName, sprinting) --Sets the state of a player local controls = player:get_player_control() if players[playerName] then players[playerName].sprinting = sprinting + local fov_old = players[playerName].fov + local fov_new = fov_old + local fade_time = .15 if sprinting == true or controls.RMB and string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and player:get_wielded_item():get_name() ~= "mcl_bows:bow" then if sprinting == true then - players[playerName].fov = math.min(players[playerName].fov + 0.05, 1.2) - players[playerName].fade_time = .15 + fov_new = math.min(players[playerName].fov + 0.05, 1.2) else - players[playerName].fov = .7 + fov_new = .7 players[playerName].fade_time = .3 end - player:set_fov(players[playerName].fov, true, players[playerName].fade_time) if sprinting == true then playerphysics.add_physics_factor(player, "speed", "mcl_sprint:sprint", mcl_sprint.SPEED) end @@ -88,12 +89,15 @@ local function setSprinting(playerName, sprinting) --Sets the state of a player and player:get_wielded_item():get_name() ~= "mcl_bows:bow_0" and player:get_wielded_item():get_name() ~= "mcl_bows:bow_1" and player:get_wielded_item():get_name() ~= "mcl_bows:bow_2" then - players[playerName].fov = math.max(players[playerName].fov - 0.05, 1.0) - player:set_fov(players[playerName].fov, true, 0.15) + fov_new = math.max(players[playerName].fov - 0.05, 1.0) if sprinting == false then playerphysics.remove_physics_factor(player, "speed", "mcl_sprint:sprint") end end + if fov_new ~= fov_old then + players[playerName].fov = fov_new + player:set_fov(fov_new, true, fade_time) + end return true end return false From 693a5317efd84eeb1141414e0b48930a09bdceec Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 28 Jul 2021 20:44:48 +0200 Subject: [PATCH 079/111] Fix non-serializable item entity unload crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some items, like shulkers or books, can have so much metadata that the corresponding item entity can not be serialized by the Minetest engine. Without this patch, dropping such an item and then moving away crashes Minetest, as it can not serialize the entity with serializeString16() when unloading a map block. The patch resets the overlong metadata of non-serializable item entities. This avoids a crash and makes it possible to retrieve a “sanitized” item without metadata when the mapblock containing the item entity is reloaded. Originally sfan5 guessed the maximum possible item entity serialization size that would not lead to a crash as 65530 bytes, but anon5 calculated it to be actually 65487 bytes. This has been experimentally verified by erlehmann. --- mods/ENTITIES/mcl_item_entity/init.lua | 28 +++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 7869b9d79..7a2758ed0 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -480,7 +480,7 @@ minetest.register_entity(":__builtin:item", { end, get_staticdata = function(self) - return minetest.serialize({ + local data = minetest.serialize({ itemstring = self.itemstring, always_collect = self.always_collect, age = self.age, @@ -488,6 +488,32 @@ minetest.register_entity(":__builtin:item", { _flowing = self._flowing, _removed = self._removed, }) + -- sfan5 guessed that the biggest serializable item + -- entity would have a size of 65530 bytes. This has + -- been experimentally verified to be still too large. + -- + -- anon5 has calculated that the biggest serializable + -- item entity has a size of exactly 65487 bytes: + -- + -- 1. serializeString16 can handle max. 65535 bytes. + -- 2. The following engine metadata is always saved: + -- • 1 byte (version) + -- • 2 byte (length prefix) + -- • 14 byte “__builtin:item” + -- • 4 byte (length prefix) + -- • 2 byte (health) + -- • 3 × 4 byte = 12 byte (position) + -- • 4 byte (yaw) + -- • 1 byte (version 2) + -- • 2 × 4 byte = 8 byte (pitch and roll) + -- 3. This leaves 65487 bytes for the serialization. + if #data > 65487 then -- would crash the engine + local stack = ItemStack(self.itemstring) + stack:get_meta():from_table(nil) + self.itemstring = stack:to_string() + return self:get_staticdata() + end + return data end, on_activate = function(self, staticdata, dtime_s) From 256de2bc365466735900dde62c749035ee700843 Mon Sep 17 00:00:00 2001 From: Nils Dagsson Moskopp Date: Thu, 29 Jul 2021 15:46:50 +0200 Subject: [PATCH 080/111] Log warning for non-serializable item entity fix --- mods/ENTITIES/mcl_item_entity/init.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 7a2758ed0..cfd141f04 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -511,6 +511,13 @@ minetest.register_entity(":__builtin:item", { local stack = ItemStack(self.itemstring) stack:get_meta():from_table(nil) self.itemstring = stack:to_string() + minetest.log( + "warning", + "Overlong item entity metadata removed: “" .. + self.itemstring .. + "” had serialized length of " .. + #data + ) return self:get_staticdata() end return data From 27e4bd6d09b8a1ea36e9b0120b5aa7b90d16cc5a Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sat, 18 Sep 2021 22:28:20 +0200 Subject: [PATCH 081/111] Fix burning entity packet spam - Use upright_sprite for 3rd person flame display, which is both closer to minecraft and allows for client side texture animation - Take care of flame HUD in the MineClone2Client --- mods/ENTITIES/mcl_burning/api.lua | 18 +++-------- mods/ENTITIES/mcl_burning/init.lua | 51 +++++++++++++----------------- 2 files changed, 27 insertions(+), 42 deletions(-) diff --git a/mods/ENTITIES/mcl_burning/api.lua b/mods/ENTITIES/mcl_burning/api.lua index 4cb19cca1..969985205 100644 --- a/mods/ENTITIES/mcl_burning/api.lua +++ b/mods/ENTITIES/mcl_burning/api.lua @@ -67,14 +67,9 @@ function mcl_burning.set_on_fire(obj, burn_time) end if not storage.burn_time or burn_time >= storage.burn_time then - if obj:is_player() and not storage.fire_hud_id then - storage.fire_hud_id = obj:hud_add({ - hud_elem_type = "image", - position = {x = 0.5, y = 0.5}, - scale = {x = -100, y = -100}, - text = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. 1, - z_index = 1000, - }) + if obj:is_player() then + mcl_burning.channels[obj]:send_all(tostring(mcl_burning.animation_frames)) + mcl_burning.channels[obj]:send_all("start") end storage.burn_time = burn_time storage.fire_damage_timer = 0 @@ -95,7 +90,6 @@ function mcl_burning.set_on_fire(obj, burn_time) fire_entity:set_properties({visual_size = size}) fire_entity:set_attach(obj, "", offset, {x = 0, y = 0, z = 0}) local fire_luaentity = fire_entity:get_luaentity() - fire_luaentity:update_frame(obj, storage) for _, other in pairs(minetest.get_objects_inside_radius(fire_entity:get_pos(), 0)) do local other_luaentity = other:get_luaentity() @@ -111,9 +105,7 @@ function mcl_burning.extinguish(obj) if mcl_burning.is_burning(obj) then local storage = mcl_burning.get_storage(obj) if obj:is_player() then - if storage.fire_hud_id then - obj:hud_remove(storage.fire_hud_id) - end + mcl_burning.channels[obj]:send_all("stop") mcl_burning.storage[obj] = {} else storage.burn_time = nil @@ -143,4 +135,4 @@ function mcl_burning.tick(obj, dtime, storage) end end end -end \ No newline at end of file +end diff --git a/mods/ENTITIES/mcl_burning/init.lua b/mods/ENTITIES/mcl_burning/init.lua index 34b7ca2d4..313e75dca 100644 --- a/mods/ENTITIES/mcl_burning/init.lua +++ b/mods/ENTITIES/mcl_burning/init.lua @@ -7,6 +7,7 @@ local get_item_group = minetest.get_item_group mcl_burning = { storage = {}, + channels = {}, animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8 } @@ -54,12 +55,11 @@ minetest.register_on_joinplayer(function(player) end mcl_burning.storage[player] = storage + mcl_burning.channels[player] = minetest.mod_channel_join("mcl_burning:" .. player:get_player_name()) end) minetest.register_on_leaveplayer(function(player) - local storage = mcl_burning.storage[player] - storage.fire_hud_id = nil - player:get_meta():set_string("mcl_burning:data", minetest.serialize(storage)) + player:get_meta():set_string("mcl_burning:data", minetest.serialize(mcl_burning.storage[player])) mcl_burning.storage[player] = nil end) @@ -68,27 +68,28 @@ minetest.register_entity("mcl_burning:fire", { initial_properties = { physical = false, collisionbox = {0, 0, 0, 0, 0, 0}, - visual = "cube", + visual = "upright_sprite", + textures = { + name = "mcl_burning_entity_flame_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.0, + }, + }, + spritediv = {x = 1, y = mcl_burning.animation_frames}, pointable = false, glow = -1, backface_culling = false, }, animation_frame = 0, animation_timer = 0, - on_step = function(self, dtime) - local parent, storage = self:sanity_check() - - if parent then - self.animation_timer = self.animation_timer + dtime - if self.animation_timer >= 0.1 then - self.animation_timer = 0 - self.animation_frame = self.animation_frame + 1 - if self.animation_frame > mcl_burning.animation_frames - 1 then - self.animation_frame = 0 - end - self:update_frame(parent, storage) - end - else + on_activate = function(self) + self.object:set_sprite({x = 0, y = 0}, mcl_burning.animation_frames, 1.0 / mcl_burning.animation_frames) + end, + on_step = function(self) + if not self:sanity_check() then self.object:remove() end end, @@ -96,23 +97,15 @@ minetest.register_entity("mcl_burning:fire", { local parent = self.object:get_attach() if not parent then - return + return false end local storage = mcl_burning.get_storage(parent) if not storage or not storage.burn_time then - return + return false end - return parent, storage - end, - update_frame = function(self, parent, storage) - local frame_overlay = "^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. self.animation_frame - local fire_texture = "mcl_burning_entity_flame_animated.png" .. frame_overlay - self.object:set_properties({textures = {"blank.png", "blank.png", fire_texture, fire_texture, fire_texture, fire_texture}}) - if parent:is_player() then - parent:hud_change(storage.fire_hud_id, "text", "mcl_burning_hud_flame_animated.png" .. frame_overlay) - end + return true end, }) From 0e15accada59737c415a0920e93b65a39e5aa2ae Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 19 Sep 2021 11:15:19 +0000 Subject: [PATCH 082/111] Enable fly in creative mode --- mods/MISC/mcl_privs/init.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index 63694ab11..5a23c00fb 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -3,3 +3,14 @@ local S = minetest.get_translator(minetest.get_current_modname()) minetest.register_privilege("maphack", { description = S("Can place and use advanced blocks like mob spawners, command blocks and barriers."), }) + +minetest.register_on_joinplayer(function(player) + local name = user:get_player_name() + local fly = false + if minetest.is_creative_enabled(name) then + fly = true + end + minetest.set_player_privs(name, { + fly = fly, + }) +end) From 18a83fa5d725c51563a2f35bf818b7c9b9041680 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 19 Sep 2021 11:18:09 +0000 Subject: [PATCH 083/111] Fix typo --- mods/MISC/mcl_privs/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index 5a23c00fb..091ddb65e 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -5,7 +5,7 @@ minetest.register_privilege("maphack", { }) minetest.register_on_joinplayer(function(player) - local name = user:get_player_name() + local name = player:get_player_name() local fly = false if minetest.is_creative_enabled(name) then fly = true From fed43586f202cd71fe374560f90b42bef18361ec Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 19 Sep 2021 11:28:07 +0000 Subject: [PATCH 084/111] fix typo --- mods/MISC/mcl_privs/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index 091ddb65e..1d1465676 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -6,7 +6,7 @@ minetest.register_privilege("maphack", { minetest.register_on_joinplayer(function(player) local name = player:get_player_name() - local fly = false + local fly = nil if minetest.is_creative_enabled(name) then fly = true end From f10d579d9c45bdddb7f2ae1935d74821b9c6a8b3 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 19 Sep 2021 12:07:21 +0000 Subject: [PATCH 085/111] Only change fly priv on join if it wasn't revoked or granted --- mods/MISC/mcl_privs/init.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index 1d1465676..c63f7c5c5 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -6,6 +6,10 @@ minetest.register_privilege("maphack", { minetest.register_on_joinplayer(function(player) local name = player:get_player_name() + + local meta = player:get_meta() + if meta:get_int("fly_changed") == 1 then return end + local fly = nil if minetest.is_creative_enabled(name) then fly = true @@ -14,3 +18,13 @@ minetest.register_on_joinplayer(function(player) fly = fly, }) end) + +for _, action in pairs({ "grant", "revoke" }) do + minetest["register_on_priv_" .. action](function(name, _, priv) + if priv == "fly" then + local player = minetest.get_player_by_name(name) + local meta = player:get_meta() + meta:set_int("fly_changed", 1) + end + end) +end \ No newline at end of file From c6003398b5f4149b3eaffe585fde40e8374c721b Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 19 Sep 2021 13:14:36 +0000 Subject: [PATCH 086/111] Remove chain armor recipes, because villagers spawn now --- mods/MISC/mcl_temp_helper_recipes/init.lua | 34 ---------------------- 1 file changed, 34 deletions(-) diff --git a/mods/MISC/mcl_temp_helper_recipes/init.lua b/mods/MISC/mcl_temp_helper_recipes/init.lua index 420cd6c2e..b7607946d 100644 --- a/mods/MISC/mcl_temp_helper_recipes/init.lua +++ b/mods/MISC/mcl_temp_helper_recipes/init.lua @@ -35,40 +35,6 @@ minetest.register_craft({ }, }) -minetest.register_craft({ - output = "mcl_armor:helmet_chain", - recipe = { - { "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - } -}) - -minetest.register_craft({ - output = "mcl_armor:leggings_chain", - recipe = { - { "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - } -}) - -minetest.register_craft({ - output = "mcl_armor:boots_chain", - recipe = { - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - } -}) - -minetest.register_craft({ - output = "mcl_armor:chestplate_chain", - recipe = { - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "xpanes:bar_flat", "xpanes:bar_flat" }, - } -}) - -- Make red sand, red sandstone and more craftable in v6 -- NOTE: When you change these, also update mcl_craftguide for the "v6" icon in -- the craft guide! From 3e54acce9db66ff7d330cbcffe20c8ae8ffcd91a Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 20 Sep 2021 09:47:24 +0200 Subject: [PATCH 087/111] fix emerald help text translation --- mods/ITEMS/mcl_core/locale/mcl_core.de.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.es.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.fr.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.pl.tr | 2 +- mods/ITEMS/mcl_core/locale/mcl_core.ru.tr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr index 0a1cbad37..b064cebbe 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Smaragd Emerald Ore=Smaragderz Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Smaragderz ist das Erz von Smaragden. Es ist sehr selten und kann nur einzeln gefunden werden, nicht in Ansammlungen. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Smaragde sind nicht besonders nützlich, aber man kann sie in der Fertigung durch Goldbarren eintauschen. +Emeralds are used in villager trades as currency.= Flint=Feuerstein Flint is a raw material.=Feuerstein ist ein Rohstoff. Flowing Lava=Fließende Lava diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr index 1e1029c0f..1937babd3 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Esmeralda Emerald Ore=Mena de esmeralda Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=El mineral esmeralda es el mineral de las esmeraldas. Es muy raro y se puede encontrar solo, no en grupos. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Las esmeraldas no son muy útiles por sí mismas, pero pueden cambiarse por lingotes de oro haciendo artesanías. +Emeralds are used in villager trades as currency.= Flint=Pedernal Flint is a raw material.=El pedernal es una materia prima. Flowing Lava=Lava que fluye diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr index 725025e48..64aadd6db 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Emeraude Emerald Ore=Minerai d'Emeraude Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Le minerai d'émeraude produit des émeraudes. Il est très rare et peut être trouvé seul, pas en filons. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Les émeraudes ne sont pas très utiles seules, mais elles peuvent être échangées contre des lingots d'or. +Emeralds are used in villager trades as currency.=Les émeraudes sont utilisées pour faire des échanges avec les villageois. Flint=Silex Flint is a raw material.=Le silex est une matière première. Flowing Lava=Lave qui coule diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr index 832a47830..68dfbd3d0 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Szmaragd Emerald Ore=Ruda szmaragdu Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Ruda szmaragdu jest bardzo rzadka i występuje samotnie, nie w grupach. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Szmaragdy nie są zbyt użyteczne same w sobie, ale można z nich wytworzyć sztabki złota. +Emeralds are used in villager trades as currency.= Flint=Krzemień Flint is a raw material.=Krzemień jest surowym materiałem. Flowing Lava=Płynąca lawa diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr index f93db7c2c..2d5b5462c 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Изумруд Emerald Ore=Изумрудная руда Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Изумрудная руда встречается очень редко и всегда по одному блоку. -Emeralds are not very useful on their own, but they can exchanged for gold ingots by crafting.=Изумруды не очень полезны сами по себе, но их можно обменять на золотые слитки. +Emeralds are used in villager trades as currency.= Flint=Кремень Flint is a raw material.=Кремень это необработанный материал. Flowing Lava=Текущая лава From e0c7e938dea19a3df5efd9fa73b61c85d17640ed Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 20 Sep 2021 07:55:51 +0000 Subject: [PATCH 088/111] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20'mods/ITEMS?= =?UTF-8?q?/mcl=5Fcore/locale/mcl=5Fcore.fr.tr'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/ITEMS/mcl_core/locale/mcl_core.fr.tr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr index 4d6a3ed43..64aadd6db 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Emeraude Emerald Ore=Minerai d'Emeraude Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Le minerai d'émeraude produit des émeraudes. Il est très rare et peut être trouvé seul, pas en filons. -Emeralds are used in villager trades as currency.=Les émeraudes ne sont pas très utiles seules, mais elles peuvent être échangées contre des lingots d'or. +Emeralds are used in villager trades as currency.=Les émeraudes sont utilisées pour faire des échanges avec les villageois. Flint=Silex Flint is a raw material.=Le silex est une matière première. Flowing Lava=Lave qui coule From e8134345d4476be032117723b5397926ff6d5199 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 20 Sep 2021 07:56:25 +0000 Subject: [PATCH 089/111] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20'mods/ITEMS?= =?UTF-8?q?/mcl=5Fcore/locale/mcl=5Fcore.de.tr'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/ITEMS/mcl_core/locale/mcl_core.de.tr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr index 8b75dfd40..b064cebbe 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.de.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.de.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Smaragd Emerald Ore=Smaragderz Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Smaragderz ist das Erz von Smaragden. Es ist sehr selten und kann nur einzeln gefunden werden, nicht in Ansammlungen. -Emeralds are used in villager trades as currency.=Smaragde sind nicht besonders nützlich, aber man kann sie in der Fertigung durch Goldbarren eintauschen. +Emeralds are used in villager trades as currency.= Flint=Feuerstein Flint is a raw material.=Feuerstein ist ein Rohstoff. Flowing Lava=Fließende Lava From b2af00db2201f1ddc20c0b9650c983402aaa10b7 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 20 Sep 2021 07:57:04 +0000 Subject: [PATCH 090/111] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20'mods/ITEMS?= =?UTF-8?q?/mcl=5Fcore/locale/mcl=5Fcore.es.tr'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/ITEMS/mcl_core/locale/mcl_core.es.tr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr index d77f45dc2..1937babd3 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.es.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.es.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Esmeralda Emerald Ore=Mena de esmeralda Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=El mineral esmeralda es el mineral de las esmeraldas. Es muy raro y se puede encontrar solo, no en grupos. -Emeralds are used in villager trades as currency.=Las esmeraldas no son muy útiles por sí mismas, pero pueden cambiarse por lingotes de oro haciendo artesanías. +Emeralds are used in villager trades as currency.= Flint=Pedernal Flint is a raw material.=El pedernal es una materia prima. Flowing Lava=Lava que fluye From e36a8c5acf48d473db9ae5807b176b94a779e15c Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 20 Sep 2021 07:58:25 +0000 Subject: [PATCH 091/111] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20'mods/ITEMS?= =?UTF-8?q?/mcl=5Fcore/locale/mcl=5Fcore.pl.tr'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/ITEMS/mcl_core/locale/mcl_core.pl.tr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr index f8dbbde6b..68dfbd3d0 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.pl.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Szmaragd Emerald Ore=Ruda szmaragdu Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Ruda szmaragdu jest bardzo rzadka i występuje samotnie, nie w grupach. -Emeralds are used in villager trades as currency.=Szmaragdy nie są zbyt użyteczne same w sobie, ale można z nich wytworzyć sztabki złota. +Emeralds are used in villager trades as currency.= Flint=Krzemień Flint is a raw material.=Krzemień jest surowym materiałem. Flowing Lava=Płynąca lawa From b0cf07a020ba353545465b8909fd88ad8725c4cd Mon Sep 17 00:00:00 2001 From: AFCMS Date: Mon, 20 Sep 2021 07:59:00 +0000 Subject: [PATCH 092/111] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20'mods/ITEMS?= =?UTF-8?q?/mcl=5Fcore/locale/mcl=5Fcore.ru.tr'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/ITEMS/mcl_core/locale/mcl_core.ru.tr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr index ad9d863b2..2d5b5462c 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.ru.tr @@ -95,7 +95,7 @@ Dirt acts as a soil for a few plants. When in light, this block may grow a grass Emerald=Изумруд Emerald Ore=Изумрудная руда Emerald ore is the ore of emeralds. It is very rare and can be found alone, not in clusters.=Изумрудная руда встречается очень редко и всегда по одному блоку. -Emeralds are used in villager trades as currency.=Изумруды не очень полезны сами по себе, но их можно обменять на золотые слитки. +Emeralds are used in villager trades as currency.= Flint=Кремень Flint is a raw material.=Кремень это необработанный материал. Flowing Lava=Текущая лава From 89e90b13eb53085a801c37c639a796a0a917cac0 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 20 Sep 2021 14:16:59 +0000 Subject: [PATCH 093/111] Use on_newplayer --- mods/MISC/mcl_privs/init.lua | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index c63f7c5c5..302557f86 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -4,12 +4,9 @@ minetest.register_privilege("maphack", { description = S("Can place and use advanced blocks like mob spawners, command blocks and barriers."), }) -minetest.register_on_joinplayer(function(player) +minetest.register_on_newplayer(function(player) local name = player:get_player_name() - local meta = player:get_meta() - if meta:get_int("fly_changed") == 1 then return end - local fly = nil if minetest.is_creative_enabled(name) then fly = true @@ -18,13 +15,3 @@ minetest.register_on_joinplayer(function(player) fly = fly, }) end) - -for _, action in pairs({ "grant", "revoke" }) do - minetest["register_on_priv_" .. action](function(name, _, priv) - if priv == "fly" then - local player = minetest.get_player_by_name(name) - local meta = player:get_meta() - meta:set_int("fly_changed", 1) - end - end) -end \ No newline at end of file From df1d8077e6123cef815bc4f30dd02838b9b84dec Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 21 Sep 2021 18:07:36 +0000 Subject: [PATCH 094/111] Some fixes for mcl_beds - remove enable_bed_night_skip setting (mcl_playersSleepingPercentage setting can be used to enable disable night skip) - make it possible to change mcl_playersSleepingPercentage ingame - fix weird bug which allowed only numbers <= 0 --- mods/ITEMS/mcl_beds/functions.lua | 39 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 01ccec851..e7306b40a 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -9,36 +9,36 @@ local weather_mod = minetest.get_modpath("mcl_weather") local explosions_mod = minetest.get_modpath("mcl_explosions") local spawn_mod = minetest.get_modpath("mcl_spawn") local worlds_mod = minetest.get_modpath("mcl_worlds") -local players_in_bed_setting = tonumber(minetest.settings:get("mcl_playersSleepingPercentage")) -- Helper functions local function get_look_yaw(pos) local n = minetest.get_node(pos) - if n.param2 == 1 then - return math.pi / 2, n.param2 - elseif n.param2 == 3 then - return -math.pi / 2, n.param2 - elseif n.param2 == 0 then - return math.pi, n.param2 + local param = n.param2 + if param == 1 then + return math.pi / 2, param + elseif param == 3 then + return -math.pi / 2, param + elseif param == 0 then + return math.pi, param else - return 0, n.param2 + return 0, param end end +local function players_in_bed_setting() + return tonumber(minetest.settings:get("mcl_playersSleepingPercentage")) +end + local function is_night_skip_enabled() - local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip") - if enable_night_skip == nil then - enable_night_skip = true - end - return enable_night_skip + return players_in_bed_setting() <= 100 end local function check_in_beds(players) if not players then players = minetest.get_connected_players() end - return players_in_bed_setting <= (#mcl_beds.player * 100) / #players + return players_in_bed_setting() <= (player_in_bed * 100) / #players end -- These monsters do not prevent sleep @@ -190,8 +190,8 @@ end local function update_formspecs(finished, ges) local ges = ges or #minetest.get_connected_players() local form_n = "size[12,5;true]" - local all_in_bed = players_in_bed_setting <= (player_in_bed * 100) / ges - local night_skip = is_night_skip_enabled() and players_in_bed_setting <= 100 + local all_in_bed = players_in_bed_setting() <= (player_in_bed * 100) / ges + local night_skip = is_night_skip_enabled() local button_leave = "button_exit[4,3;4,0.75;leave;"..F(S("Leave bed")).."]" local button_abort = "button_exit[4,3;4,0.75;leave;"..F(S("Abort sleep")).."]" local bg_presleep = "bgcolor[#00000080;true]" @@ -204,7 +204,7 @@ local function update_formspecs(finished, ges) return elseif not is_sp then local text = S("Players in bed: @1/@2", player_in_bed, ges) - if not night_skip or players_in_bed_setting > 100 then + if not night_skip then text = text .. "\n" .. S("Note: Night skip is disabled.") form_n = form_n .. bg_presleep form_n = form_n .. button_leave @@ -214,10 +214,10 @@ local function update_formspecs(finished, ges) form_n = form_n .. button_abort else local comment = "You will fall asleep when " - if players_in_bed_setting == 100 then + if players_in_bed_setting() == 100 then comment = S(comment .. "all players are in bed.") else - comment = S(comment .. "@1% of all players are in bed.", players_in_bed_setting) + comment = S(comment .. "@1% of all players are in bed.", players_in_bed_setting()) end text = text .. "\n" .. comment form_n = form_n .. bg_presleep @@ -347,7 +347,6 @@ function mcl_beds.on_rightclick(pos, player, is_top) end end - -- Callbacks minetest.register_on_joinplayer(function(player) local meta = player:get_meta() From 71f448537cb523c9f8287b630ccce6f1ddd91cca Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 21 Sep 2021 18:14:24 +0000 Subject: [PATCH 095/111] Remove unused setting from settingtypes.txt --- settingtypes.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/settingtypes.txt b/settingtypes.txt index 89e11833f..542711675 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -36,11 +36,9 @@ enable_bed_respawn (Respawn at bed) bool true # How many players have to sleep to skip the night, in percent. # Setting to 0 will mean 1 player is always enough to skip the night. Setting above 100 will prevent skipping the night. # 100 by default. +# The setting can be changed ingame using `/set mcl_playersSleepingPercentage ` mcl_playersSleepingPercentage (Players Sleeping Percentage) int 100 -# If enabled, the night can be skipped if all players are in bed. -# This setting is only read at startup. -enable_bed_night_skip (Skip night when sleeping) bool true # Normally, players drop all their items when they die. Enable this # setting, so players always keep their inventory on death. mcl_keepInventory (Keep inventory on death) bool false From e83438e42cb677e6336f52e5e17973fcbef5663c Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 21 Sep 2021 18:19:07 +0000 Subject: [PATCH 096/111] Update mcl_bed README.txt --- mods/ITEMS/mcl_beds/README.txt | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/mods/ITEMS/mcl_beds/README.txt b/mods/ITEMS/mcl_beds/README.txt index cda6ebd92..34b493702 100644 --- a/mods/ITEMS/mcl_beds/README.txt +++ b/mods/ITEMS/mcl_beds/README.txt @@ -12,15 +12,7 @@ Authors of media (textures) BlockMen (CC BY-SA 3.0) This mod adds a bed to Minetest which allows to skip the night. -To sleep, rightclick the bed. If playing in singleplayer mode the night gets skipped -immediately. If playing multiplayer you get shown how many other players are in bed too, -if all players are sleeping the night gets skipped. The night skip can be forced if more -than 50% of the players are lying in bed and use this option. - -Another feature is a controlled respawning. If you have slept in bed (not just lying in -it) your respawn point is set to the beds location and you will respawn there after +To sleep, rightclick the bed. +Another feature is a controlled respawning. If you have slept in bed your respawn point is set to the beds location and you will respawn there after death. -You can disable the respawn at beds by setting "enable_bed_respawn = false" in -minetest.conf. -You can disable the night skip feature by setting "enable_bed_night_skip = false" in -minetest.conf or by using the /set command in-game. +Use the mcl_playersSleepingPercentage setting to enable/disable night skipping or set a percentage of how many players need to sleep to skip the night. \ No newline at end of file From 8697b38d60325f289eb75fd19b83e86e877946bc Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 27 Sep 2021 20:00:11 +0000 Subject: [PATCH 097/111] Remove on_newplayer ... --- mods/MISC/mcl_privs/init.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index 302557f86..c63f7c5c5 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -4,9 +4,12 @@ minetest.register_privilege("maphack", { description = S("Can place and use advanced blocks like mob spawners, command blocks and barriers."), }) -minetest.register_on_newplayer(function(player) +minetest.register_on_joinplayer(function(player) local name = player:get_player_name() + local meta = player:get_meta() + if meta:get_int("fly_changed") == 1 then return end + local fly = nil if minetest.is_creative_enabled(name) then fly = true @@ -15,3 +18,13 @@ minetest.register_on_newplayer(function(player) fly = fly, }) end) + +for _, action in pairs({ "grant", "revoke" }) do + minetest["register_on_priv_" .. action](function(name, _, priv) + if priv == "fly" then + local player = minetest.get_player_by_name(name) + local meta = player:get_meta() + meta:set_int("fly_changed", 1) + end + end) +end \ No newline at end of file From 03be73656648136fdabff2dd68c6e44ed184f475 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 27 Sep 2021 20:13:12 +0000 Subject: [PATCH 098/111] Dont skip night if no players are in bed --- mods/ITEMS/mcl_beds/functions.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index e7306b40a..e2bece033 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -38,6 +38,9 @@ local function check_in_beds(players) if not players then players = minetest.get_connected_players() end + if player_in_bed < 0 then + return false + end return players_in_bed_setting() <= (player_in_bed * 100) / #players end From 16c73c1cb652b02f77e6140e9ad41f602d5f29aa Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 28 Sep 2021 13:16:19 +0000 Subject: [PATCH 099/111] Add forgotten `=` --- mods/ITEMS/mcl_beds/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index e2bece033..062219294 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -38,7 +38,7 @@ local function check_in_beds(players) if not players then players = minetest.get_connected_players() end - if player_in_bed < 0 then + if player_in_bed <= 0 then return false end return players_in_bed_setting() <= (player_in_bed * 100) / #players From e9437e9e1e623a493ecf2abbac91fefd775c5aa4 Mon Sep 17 00:00:00 2001 From: AFCMS Date: Wed, 29 Sep 2021 21:06:51 +0200 Subject: [PATCH 100/111] fix crash then using function in `_mcl_armor_[texture, preview]` tool field --- mods/ITEMS/mcl_enchanting/engine.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index d2a749947..6050aeed2 100644 --- a/mods/ITEMS/mcl_enchanting/engine.lua +++ b/mods/ITEMS/mcl_enchanting/engine.lua @@ -270,8 +270,14 @@ function mcl_enchanting.initialize() new_def.groups.not_in_creative_inventory = 1 new_def.groups.not_in_craft_guide = 1 new_def.groups.enchanted = 1 - new_def._mcl_armor_texture = new_def._mcl_armor_texture and new_def._mcl_armor_texture .. mcl_enchanting.overlay - new_def._mcl_armor_preview = new_def._mcl_armor_preview and new_def._mcl_armor_preview .. mcl_enchanting.overlay + + if new_def._mcl_armor_texture and not type(new_def._mcl_armor_texture) == "function" then + new_def._mcl_armor_texture = new_def._mcl_armor_texture .. mcl_enchanting.overlay + end + if new_def._mcl_armor_preview and not type(new_def._mcl_armor_preview) == "function" then + new_def._mcl_armor_preview = new_def._mcl_armor_preview .. mcl_enchanting.overlay + end + new_def._mcl_enchanting_enchanted_tool = new_name new_def.after_use = get_after_use_callback(itemdef) local register_list = register_item_list From a410d173069baf3d38f5fe5a704e4db562e5dd8a Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 30 Sep 2021 20:14:13 +0000 Subject: [PATCH 101/111] Fix that all of new players' default_privs are removed --- mods/MISC/mcl_privs/init.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index c63f7c5c5..f06ff3582 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -6,7 +6,6 @@ minetest.register_privilege("maphack", { minetest.register_on_joinplayer(function(player) local name = player:get_player_name() - local meta = player:get_meta() if meta:get_int("fly_changed") == 1 then return end @@ -14,12 +13,12 @@ minetest.register_on_joinplayer(function(player) if minetest.is_creative_enabled(name) then fly = true end - minetest.set_player_privs(name, { - fly = fly, - }) + local player_privs = minetest.get_player_privs(name) + player_privs.fly = fly + minetest.set_player_privs(name, player_privs) end) -for _, action in pairs({ "grant", "revoke" }) do +for _, action in pairs({"grant", "revoke"}) do minetest["register_on_priv_" .. action](function(name, _, priv) if priv == "fly" then local player = minetest.get_player_by_name(name) From 8e3f9d216944d258cd385223db037ef1882deb63 Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 09:22:27 +0000 Subject: [PATCH 102/111] add basic lightning API --- mods/ENVIRONMENT/lightning/init.lua | 75 ++++++++++++++++++----------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/mods/ENVIRONMENT/lightning/init.lua b/mods/ENVIRONMENT/lightning/init.lua index 3d5955d6e..3230f0b0a 100644 --- a/mods/ENVIRONMENT/lightning/init.lua +++ b/mods/ENVIRONMENT/lightning/init.lua @@ -24,13 +24,14 @@ local get_objects_inside_radius = minetest.get_objects_inside_radius local get_item_group = minetest.get_item_group lightning = { - interval_low = 17, - interval_high = 503, - range_h = 100, - range_v = 50, - size = 100, - -- disable this to stop lightning mod from striking - auto = true, + interval_low = 17, + interval_high = 503, + range_h = 100, + range_v = 50, + size = 100, + -- disable this to stop lightning mod from striking + auto = true, + on_strike_functions = {}, } local rng = PcgRandom(32321123312123) @@ -54,6 +55,18 @@ end minetest.register_globalstep(revertsky) +-- lightning strike API + +-- See README.md +--[[ + lightning.register_on_strike(function(pos, pos2, objects) + -- code + end) +]] +function lightning.register_on_strike(func) + table.insert(lightning.on_strike_functions, func) +end + -- select a random strike point, midpoint local function choose_pos(pos) if not pos then @@ -79,14 +92,14 @@ local function choose_pos(pos) pos.z = math.floor(pos.z - (lightning.range_h / 2) + rng:next(1, lightning.range_h)) end - local b, pos2 = line_of_sight(pos, {x = pos.x, y = pos.y - lightning.range_v, z = pos.z}, 1) + local b, pos2 = line_of_sight(pos, { x = pos.x, y = pos.y - lightning.range_v, z = pos.z }, 1) -- nothing but air found if b then return nil, nil end - local n = get_node({x = pos2.x, y = pos2.y - 1/2, z = pos2.z}) + local n = get_node({ x = pos2.x, y = pos2.y - 1/2, z = pos2.z }) if n.name == "air" or n.name == "ignore" then return nil, nil end @@ -94,7 +107,6 @@ local function choose_pos(pos) return pos, pos2 end --- lightning strike API -- * pos: optional, if not given a random pos will be chosen -- * returns: bool - success if a strike happened function lightning.strike(pos) @@ -108,21 +120,30 @@ function lightning.strike(pos) if not pos then return false end + local objects = get_objects_inside_radius(pos2, 3.5) + if lightning.on_strike_functions then + for _, func in pairs(lightning.on_strike_functions) do + func(pos, pos2, objects) + end + end +end + + +lightning.register_on_strike(function(pos, pos2, objects) + local particle_pos = vector.offset(pos2, 0, (lightning.size / 2) + 0.5, 0) + local particle_size = lightning.size * 10 + local time = 0.2 add_particlespawner({ amount = 1, - time = 0.2, + time = time, -- make it hit the top of a block exactly with the bottom - minpos = {x = pos2.x, y = pos2.y + (lightning.size / 2) + 1/2, z = pos2.z }, - maxpos = {x = pos2.x, y = pos2.y + (lightning.size / 2) + 1/2, z = pos2.z }, - minvel = {x = 0, y = 0, z = 0}, - maxvel = {x = 0, y = 0, z = 0}, - minacc = {x = 0, y = 0, z = 0}, - maxacc = {x = 0, y = 0, z = 0}, - minexptime = 0.2, - maxexptime = 0.2, - minsize = lightning.size * 10, - maxsize = lightning.size * 10, + minpos = particle_pos, + maxpos = particle_pos, + minexptime = time, + maxexptime = time, + minsize = particle_size, + maxsize = particle_size, collisiondetection = true, vertical = true, -- to make it appear hitting the node that will get set on fire, make sure @@ -135,10 +156,7 @@ function lightning.strike(pos) sound_play({ name = "lightning_thunder", gain = 10 }, { pos = pos, max_hear_distance = 500 }, true) -- damage nearby objects, transform mobs - -- TODO: use an API insteed of hardcoding this behaviour - local objs = get_objects_inside_radius(pos2, 3.5) - for o=1, #objs do - local obj = objs[o] + for _, obj in pairs(objects) do local lua = obj:get_luaentity() -- pig → zombie pigman (no damage) if lua and lua.name == "mobs_mc:pig" then @@ -155,7 +173,7 @@ function lightning.strike(pos) end obj:set_properties({textures = lua.base_texture}) -- villager → witch (no damage) - --elseif lua and lua.name == "mobs_mc:villager" then + -- elseif lua and lua.name == "mobs_mc:villager" then -- Witches are incomplete, this code is unused -- TODO: Enable this code when witches are working. --[[ @@ -172,7 +190,7 @@ function lightning.strike(pos) obj:set_yaw(rot) -- Other objects: Just damage else - mcl_util.deal_damage(obj, 5, {type = "lightning_bolt"}) + mcl_util.deal_damage(obj, 5, { type = "lightning_bolt" }) end end @@ -223,8 +241,7 @@ function lightning.strike(pos) end end end - -end +end) -- if other mods disable auto lightning during initialization, don't trigger the first lightning. after(5, function(dtime) From e4af02ea526ef32da38ca7094f13b1c7c128bc83 Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 09:54:58 +0000 Subject: [PATCH 103/111] Add function to replace mobs --- mods/CORE/mcl_util/init.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index a7504af08..363b9b5fe 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -538,3 +538,12 @@ function mcl_util.get_object_name(object) return luaentity.nametag and luaentity.nametag ~= "" and luaentity.nametag or luaentity.description or luaentity.name end end + +function mcl_util.replace_mob(obj, mob) + local rot = obj:get_yaw() + local pos = obj:get_pos() + obj:remove() + obj = minetest.add_entity(pos, mob) + obj:set_yaw(rot) + return obj +end From 463fe2af5f3343dcecefec9eb5147f34ec04cb3d Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 09:57:36 +0000 Subject: [PATCH 104/111] use mcl_util.replace_mob function to simplify lightning code --- mods/ENVIRONMENT/lightning/init.lua | 38 +++++++---------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/mods/ENVIRONMENT/lightning/init.lua b/mods/ENVIRONMENT/lightning/init.lua index 3230f0b0a..5568e63fc 100644 --- a/mods/ENVIRONMENT/lightning/init.lua +++ b/mods/ENVIRONMENT/lightning/init.lua @@ -128,8 +128,6 @@ function lightning.strike(pos) end end - - lightning.register_on_strike(function(pos, pos2, objects) local particle_pos = vector.offset(pos2, 0, (lightning.size / 2) + 0.5, 0) local particle_size = lightning.size * 10 @@ -158,37 +156,19 @@ lightning.register_on_strike(function(pos, pos2, objects) -- damage nearby objects, transform mobs for _, obj in pairs(objects) do local lua = obj:get_luaentity() - -- pig → zombie pigman (no damage) if lua and lua.name == "mobs_mc:pig" then - local rot = obj:get_yaw() - obj:remove() - obj = add_entity(pos2, "mobs_mc:pigman") - obj:set_yaw(rot) - -- mooshroom: toggle color red/brown (no damage) + mcl_util.replace_mob(obj, "mobs_mc:pigman") elseif lua and lua.name == "mobs_mc:mooshroom" then if lua.base_texture[1] == "mobs_mc_mooshroom.png" then lua.base_texture = { "mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } else lua.base_texture = { "mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png" } end - obj:set_properties({textures = lua.base_texture}) - -- villager → witch (no damage) - -- elseif lua and lua.name == "mobs_mc:villager" then - -- Witches are incomplete, this code is unused - -- TODO: Enable this code when witches are working. - --[[ - local rot = obj:get_yaw() - obj:remove() - obj = minetest.add_entity(pos2, "mobs_mc:witch") - obj:set_yaw(rot) - ]] - -- charged creeper + obj:set_properties({ textures = lua.base_texture }) + elseif lua and lua.name == "mobs_mc:villager" then + mcl_util.replace_mob(obj, "mobs_mc:witch") elseif lua and lua.name == "mobs_mc:creeper" then - local rot = obj:get_yaw() - obj:remove() - obj = add_entity(pos2, "mobs_mc:creeper_charged") - obj:set_yaw(rot) - -- Other objects: Just damage + mcl_util.replace_mob(obj, "mobs_mc:creeper_charged") else mcl_util.deal_damage(obj, 5, { type = "lightning_bolt" }) end @@ -204,7 +184,7 @@ lightning.register_on_strike(function(pos, pos2, objects) local name = player:get_player_name() if ps[name] == nil then ps[name] = {p = player, sky = sky} - mcl_weather.skycolor.add_layer("lightning", {{r=255,g=255,b=255}}, true) + mcl_weather.skycolor.add_layer("lightning", { { r = 255, g = 255, b = 255 } }, true) mcl_weather.skycolor.active = true end end @@ -219,7 +199,7 @@ lightning.register_on_strike(function(pos, pos2, objects) if rng:next(1,100) <= 3 then skeleton_lightning = true end - if get_item_group(get_node({x = pos2.x, y = pos2.y - 1, z = pos2.z}).name, "liquid") < 1 then + if get_item_group(get_node({ x = pos2.x, y = pos2.y - 1, z = pos2.z }).name, "liquid") < 1 then if get_node(pos2).name == "air" then -- Low chance for a lightning to spawn skeleton horse + skeletons if skeleton_lightning then @@ -228,7 +208,7 @@ lightning.register_on_strike(function(pos, pos2, objects) local angle, posadd angle = math.random(0, math.pi*2) for i=1,3 do - posadd = {x=math.cos(angle),y=0,z=math.sin(angle)} + posadd = { x=math.cos(angle),y=0,z=math.sin(angle) } posadd = vector.normalize(posadd) local mob = add_entity(vector.add(pos2, posadd), "mobs_mc:skeleton") mob:set_yaw(angle-math.pi/2) @@ -237,7 +217,7 @@ lightning.register_on_strike(function(pos, pos2, objects) -- Cause a fire else - set_node(pos2, {name = "mcl_fire:fire"}) + set_node(pos2, { name = "mcl_fire:fire" }) end end end From fe91d7f3e0a5c629cb1f3abad593671ee851ee39 Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 10:07:45 +0000 Subject: [PATCH 105/111] use mcl_util.replace_mob function to simplify dispenser code --- mods/ITEMS/REDSTONE/mcl_dispensers/init.lua | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua index 82d53c806..47acacbb9 100644 --- a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua @@ -203,12 +203,8 @@ local dispenserdef = { else minetest.add_item(droppos, mobs_mc.items.mushroom_red .. " 5") end - local oldyaw = obj:get_yaw() - obj:remove() - local cow = minetest.add_entity(pos, "mobs_mc:cow") - cow:set_yaw(oldyaw) - obj = cow - entity = cow:get_luaentity() + obj = mcl_util.replace_mob(obj, "mobs_mc:cow") + entity = obj:get_luaentity() used = true end if used then From 9188467a6adfdc6bd8edfeb8f156c510ce7ab1b0 Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 12:31:19 +0000 Subject: [PATCH 106/111] add API.md for lightning mod --- mods/ENVIRONMENT/lightning/API.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 mods/ENVIRONMENT/lightning/API.md diff --git a/mods/ENVIRONMENT/lightning/API.md b/mods/ENVIRONMENT/lightning/API.md new file mode 100644 index 000000000..6a4dd11cf --- /dev/null +++ b/mods/ENVIRONMENT/lightning/API.md @@ -0,0 +1,31 @@ +# lightning +Lightning mod for MineClone2 with the following API: + +## lightning.register_on_strike(function(pos, pos2, objects)) +Custom function called when a lightning strikes. + +* `pos`: impact position +* `pos2`: rounded node position where fire is placed +* `objects`: table with ObjectRefs of all objects within a radius of 3.5 around pos2 + +## lightning.strike(pos) +Let a lightning strike. + +* pos: optional, if not given a random pos will be chosen +* returns: bool - success if a strike happened + + +### Examples: + +``` +lightning.register_on_strike(function(pos, pos2, objects) + for _, obj in pairs(objects) do + obj:remove() + end + minetest.add_entity(pos, "mobs_mc:sheep") +end) + +minetest.register_on_respawnplayer(function(player) + lightning.strike(player:get_pos()) +end) +``` \ No newline at end of file From 72ea9069bd848eb4bcbd030bc32b859370c5cef5 Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 12:35:05 +0000 Subject: [PATCH 107/111] correct lightning API.md a bit --- mods/ENVIRONMENT/lightning/API.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENVIRONMENT/lightning/API.md b/mods/ENVIRONMENT/lightning/API.md index 6a4dd11cf..ad4f0a3b4 100644 --- a/mods/ENVIRONMENT/lightning/API.md +++ b/mods/ENVIRONMENT/lightning/API.md @@ -11,8 +11,8 @@ Custom function called when a lightning strikes. ## lightning.strike(pos) Let a lightning strike. -* pos: optional, if not given a random pos will be chosen -* returns: bool - success if a strike happened +* `pos`: optional, if not given a random pos will be chosen +* `returns`: bool - success if a strike happened ### Examples: From 03829dd51884c92fae3d8ee0dd04f3dad1155dec Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 12:35:50 +0000 Subject: [PATCH 108/111] fix typo --- mods/ENVIRONMENT/lightning/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENVIRONMENT/lightning/init.lua b/mods/ENVIRONMENT/lightning/init.lua index 5568e63fc..b234092af 100644 --- a/mods/ENVIRONMENT/lightning/init.lua +++ b/mods/ENVIRONMENT/lightning/init.lua @@ -57,7 +57,7 @@ minetest.register_globalstep(revertsky) -- lightning strike API --- See README.md +-- See API.md --[[ lightning.register_on_strike(function(pos, pos2, objects) -- code From 0584d16569103bb5cd15c5e5041efb842d5b8784 Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 9 Sep 2021 13:21:33 +0000 Subject: [PATCH 109/111] add lightning API support for mobs --- mods/ENVIRONMENT/lightning/init.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/ENVIRONMENT/lightning/init.lua b/mods/ENVIRONMENT/lightning/init.lua index b234092af..83494462f 100644 --- a/mods/ENVIRONMENT/lightning/init.lua +++ b/mods/ENVIRONMENT/lightning/init.lua @@ -156,6 +156,10 @@ lightning.register_on_strike(function(pos, pos2, objects) -- damage nearby objects, transform mobs for _, obj in pairs(objects) do local lua = obj:get_luaentity() + if lua and lua._on_strike then + lua._on_strike(lua, pos, pos2, objects) + end + -- remove this when mob API is done if lua and lua.name == "mobs_mc:pig" then mcl_util.replace_mob(obj, "mobs_mc:pigman") elseif lua and lua.name == "mobs_mc:mooshroom" then From 9ccf8de606c4ce4e6b903ac3ce6727d01f3d5160 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 9 Oct 2021 14:41:56 +0000 Subject: [PATCH 110/111] Fix crash on startup if mcl_playersSleepingPercentage is not defined (#1874) --- mods/ITEMS/mcl_beds/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 062219294..b8478fc1f 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -27,7 +27,7 @@ local function get_look_yaw(pos) end local function players_in_bed_setting() - return tonumber(minetest.settings:get("mcl_playersSleepingPercentage")) + return tonumber(minetest.settings:get("mcl_playersSleepingPercentage")) or 100 end local function is_night_skip_enabled() From 1c458a2e7258565e0d98050263cf98ec17607c71 Mon Sep 17 00:00:00 2001 From: epCode Date: Fri, 15 Oct 2021 12:00:37 -0700 Subject: [PATCH 111/111] Add crossbows --- mods/ITEMS/mcl_bows/arrow.lua | 6 +- mods/ITEMS/mcl_bows/crossbow.lua | 454 ++++++++ mods/ITEMS/mcl_bows/init.lua | 6 + .../ITEMS/mcl_bows/models/mcl_bows_rocket.b3d | Bin 0 -> 11758 bytes .../ITEMS/mcl_bows/models/mcl_bows_rocket.mtl | 10 + .../ITEMS/mcl_bows/models/mcl_bows_rocket.obj | 1016 +++++++++++++++++ mods/ITEMS/mcl_bows/rocket.lua | 706 ++++++++++++ .../sounds/mcl_bows_crossbow_drawback_0.ogg | Bin 0 -> 13529 bytes .../sounds/mcl_bows_crossbow_drawback_1.ogg | Bin 0 -> 13401 bytes .../sounds/mcl_bows_crossbow_drawback_2.ogg | Bin 0 -> 10139 bytes .../sounds/mcl_bows_crossbow_load.ogg | Bin 0 -> 7627 bytes .../sounds/mcl_bows_crossbow_shoot.ogg | Bin 0 -> 9767 bytes .../mcl_bows/sounds/mcl_bows_firework.ogg | Bin 0 -> 42143 bytes .../sounds/mcl_bows_firework_soft.ogg | Bin 0 -> 55786 bytes .../mcl_bows/textures/mcl_bows_crossbow.png | Bin 0 -> 2311 bytes .../mcl_bows/textures/mcl_bows_crossbow_0.png | Bin 0 -> 2369 bytes .../mcl_bows/textures/mcl_bows_crossbow_1.png | Bin 0 -> 2383 bytes .../mcl_bows/textures/mcl_bows_crossbow_2.png | Bin 0 -> 2362 bytes .../mcl_bows/textures/mcl_bows_crossbow_3.png | Bin 0 -> 2794 bytes .../textures/mcl_bows_firework_blue.png | Bin 0 -> 630 bytes .../textures/mcl_bows_firework_green.png | Bin 0 -> 627 bytes .../textures/mcl_bows_firework_red.png | Bin 0 -> 622 bytes .../textures/mcl_bows_firework_white.png | Bin 0 -> 1577 bytes .../textures/mcl_bows_firework_yellow.png | Bin 0 -> 1717 bytes .../mcl_bows/textures/mcl_bows_rocket.png | Bin 0 -> 2133 bytes .../textures/mcl_bows_rocket_particle.png | Bin 0 -> 4675 bytes mods/ITEMS/mcl_enchanting/enchantments.lua | 14 +- mods/ITEMS/mcl_mobspawners/init.lua | 3 +- mods/ITEMS/mcl_potions/tipped_arrow.lua | 2 +- mods/PLAYER/mcl_player/init.lua | 6 +- mods/PLAYER/mcl_playerplus/init.lua | 13 + 31 files changed, 2221 insertions(+), 15 deletions(-) create mode 100644 mods/ITEMS/mcl_bows/crossbow.lua create mode 100644 mods/ITEMS/mcl_bows/models/mcl_bows_rocket.b3d create mode 100644 mods/ITEMS/mcl_bows/models/mcl_bows_rocket.mtl create mode 100644 mods/ITEMS/mcl_bows/models/mcl_bows_rocket.obj create mode 100644 mods/ITEMS/mcl_bows/rocket.lua create mode 100644 mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_drawback_0.ogg create mode 100644 mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_drawback_1.ogg create mode 100644 mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_drawback_2.ogg create mode 100644 mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_load.ogg create mode 100644 mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_shoot.ogg create mode 100644 mods/ITEMS/mcl_bows/sounds/mcl_bows_firework.ogg create mode 100644 mods/ITEMS/mcl_bows/sounds/mcl_bows_firework_soft.ogg create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_0.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_1.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_2.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_3.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_firework_blue.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_firework_green.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_firework_red.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_firework_white.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_firework_yellow.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_rocket.png create mode 100644 mods/ITEMS/mcl_bows/textures/mcl_bows_rocket_particle.png diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 9a22ee622..343707617 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -43,7 +43,7 @@ S("An arrow fired from a bow has a regular damage of 1-9. At full charge, there' S("Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons."), _doc_items_usagehelp = S("To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it."), inventory_image = "mcl_bows_arrow_inv.png", - groups = { ammo=1, ammo_bow=1, ammo_bow_regular=1 }, + groups = { ammo=1, ammo_bow=1, ammo_bow_regular=1, ammo_crossbow=1 }, _on_dispense = function(itemstack, dispenserpos, droppos, dropnode, dropdir) -- Shoot arrow local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51)) @@ -324,7 +324,9 @@ function ARROW_ENTITY.on_step(self, dtime) end if not obj:is_player() then mcl_burning.extinguish(self.object) - self.object:remove() + if self._piercing == 0 then + self.object:remove() + end end return end diff --git a/mods/ITEMS/mcl_bows/crossbow.lua b/mods/ITEMS/mcl_bows/crossbow.lua new file mode 100644 index 000000000..e3124156b --- /dev/null +++ b/mods/ITEMS/mcl_bows/crossbow.lua @@ -0,0 +1,454 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +mcl_bows_s = {} + +-- local arrows = { +-- ["mcl_bows:arrow"] = "mcl_bows:arrow_entity", +-- } + +local GRAVITY = 9.81 +local BOW_DURABILITY = 385 + +-- Charging time in microseconds +local _BOW_CHARGE_TIME_HALF = 350000 -- bow level 1 +local _BOW_CHARGE_TIME_FULL = 900000 -- bow level 2 (full charge) + +local BOW_CHARGE_TIME_HALF = 350000 -- bow level 1 +local BOW_CHARGE_TIME_FULL = 900000 -- bow level 2 (full charge) + +-- Factor to multiply with player speed while player uses bow +-- This emulates the sneak speed. +local PLAYER_USE_CROSSBOW_SPEED = tonumber(minetest.settings:get("movement_speed_crouch")) / tonumber(minetest.settings:get("movement_speed_walk")) + +-- TODO: Use Minecraft speed (ca. 53 m/s) +-- Currently nerfed because at full speed the arrow would easily get out of the range of the loaded map. +local BOW_MAX_SPEED = 68 + +local function play_load_sound(id, pos) + minetest.sound_play("mcl_bows_crossbow_drawback_"..id, {pos=pos, max_hear_distance=12}, true) +end + +--[[ Store the charging state of each player. +keys: player name +value: +nil = not charging or player not existing +number: currently charging, the number is the time from minetest.get_us_time + in which the charging has started +]] +local bow_load = {} + +-- Another player table, this one stores the wield index of the bow being charged +local bow_index = {} + +function mcl_bows_s.shoot_arrow_crossbow(arrow_item, pos, dir, yaw, shooter, power, damage, is_critical, crossbow_stack, collectable) + local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, arrow_item.."_entity") + if power == nil then + power = BOW_MAX_SPEED --19 + end + if damage == nil then + damage = 3 + end + local knockback + if crossbow_stack then + local enchantments = mcl_enchanting.get_enchantments(crossbow_stack) + if enchantments.piercing then + obj:get_luaentity()._piercing = 1 * enchantments.piercing + else + obj:get_luaentity()._piercing = 0 + end + end + obj:set_velocity({x=dir.x*power, y=dir.y*power, z=dir.z*power}) + obj:set_acceleration({x=0, y=-GRAVITY, z=0}) + obj:set_yaw(yaw-math.pi/2) + local le = obj:get_luaentity() + le._shooter = shooter + le._source_object = shooter + le._damage = damage + le._is_critical = is_critical + le._startpos = pos + le._knockback = knockback + le._collectable = collectable + minetest.sound_play("mcl_bows_crossbow_shoot", {pos=pos, max_hear_distance=16}, true) + if shooter and shooter:is_player() then + if obj:get_luaentity().player == "" then + obj:get_luaentity().player = shooter + end + obj:get_luaentity().node = shooter:get_inventory():get_stack("main", 1):get_name() + end + return obj +end + +local function get_arrow(player) + local inv = player:get_inventory() + local arrow_stack, arrow_stack_id + for i=1, inv:get_size("main") do + local it = inv:get_stack("main", i) + if not it:is_empty() and minetest.get_item_group(it:get_name(), "ammo_crossbow") ~= 0 then + arrow_stack = it + arrow_stack_id = i + break + end + end + return arrow_stack, arrow_stack_id +end + +local function player_shoot_arrow(itemstack, player, power, damage, is_critical) + local has_multishot_enchantment = mcl_enchanting.has_enchantment(player:get_wielded_item(), "multishot") + local arrow_itemstring = wielditem:get_meta():get("arrow") + + if not arrow_itemstring then + return false + end + + local playerpos = player:get_pos() + local dir = player:get_look_dir() + local yaw = player:get_look_horizontal() + + if has_multishot_enchantment then + mcl_bows_s.shoot_arrow_crossbow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, {x=dir.x, y=dir.y, z=dir.z + .2}, yaw, player, power, damage, is_critical, player:get_wielded_item(), false) + mcl_bows_s.shoot_arrow_crossbow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, {x=dir.x, y=dir.y, z=dir.z - .2}, yaw, player, power, damage, is_critical, player:get_wielded_item(), false) + mcl_bows_s.shoot_arrow_crossbow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, dir, yaw, player, power, damage, is_critical, player:get_wielded_item(), true) + else + mcl_bows_s.shoot_arrow_crossbow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, dir, yaw, player, power, damage, is_critical, player:get_wielded_item(), true) + end + return true +end + +-- Bow item, uncharged state +minetest.register_tool("mcl_bows:crossbow", { + description = S("Corssbow"), + _tt_help = S("Launches arrows"), + _doc_items_longdesc = S("Bows are ranged weapons to shoot arrows at your foes.").."\n".. +S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead."), + _doc_items_usagehelp = S("To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot."), + _doc_items_durability = BOW_DURABILITY, + inventory_image = "mcl_bows_crossbow.png", + wield_scale = mcl_vars.tool_wield_scale, + stack_max = 1, + range = 4, + -- Trick to disable digging as well + on_use = function() return end, + on_place = function(itemstack, player, pointed_thing) + if pointed_thing and pointed_thing.type == "node" then + -- Call on_rightclick if the pointed node defines it + local node = minetest.get_node(pointed_thing.under) + if player and not player:get_player_control().sneak then + if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then + return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, player, itemstack) or itemstack + end + end + end + + itemstack:get_meta():set_string("active", "true") + return itemstack + end, + on_secondary_use = function(itemstack) + itemstack:get_meta():set_string("active", "true") + return itemstack + end, + groups = {weapon=1,weapon_ranged=1,crossbow=1,enchantability=1}, + _mcl_uses = 326, +}) + +minetest.register_tool("mcl_bows:crossbow_loaded", { + description = S("Corssbow"), + _tt_help = S("Launches arrows"), + _doc_items_longdesc = S("Corssbow are ranged weapons to shoot arrows at your foes.").."\n".. +S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead."), + _doc_items_usagehelp = S("To use the corssbow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to load an arrow into the chamber, then to shoot press left mouse."), + _doc_items_durability = BOW_DURABILITY, + inventory_image = "mcl_bows_crossbow_3.png", + wield_scale = mcl_vars.tool_wield_scale, + stack_max = 1, + range = 4, + -- Trick to disable digging as well + on_use = function() return end, + on_place = function(itemstack, player, pointed_thing) + if pointed_thing and pointed_thing.type == "node" then + -- Call on_rightclick if the pointed node defines it + local node = minetest.get_node(pointed_thing.under) + if player and not player:get_player_control().sneak then + if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then + return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, player, itemstack) or itemstack + end + end + end + + itemstack:get_meta():set_string("active", "true") + return itemstack + end, + on_secondary_use = function(itemstack) + itemstack:get_meta():set_string("active", "true") + return itemstack + end, + groups = {weapon=1,weapon_ranged=1,crossbow=1,enchantability=1}, + _mcl_uses = 326, +}) + +-- Iterates through player inventory and resets all the bows in "charging" state back to their original stage +local function reset_bows(player) + local inv = player:get_inventory() + local list = inv:get_list("main") + for place, stack in pairs(list) do + if stack:get_name() == "mcl_bows:crossbow" or stack:get_name() == "mcl_bows:crossbow_enchanted" then + stack:get_meta():set_string("active", "") + elseif stack:get_name()=="mcl_bows:crossbow_0" or stack:get_name()=="mcl_bows:crossbow_1" or stack:get_name()=="mcl_bows:crossbow_2" then + stack:set_name("mcl_bows:crossbow") + stack:get_meta():set_string("active", "") + list[place] = stack + elseif stack:get_name()=="mcl_bows:crossbow_0_enchanted" or stack:get_name()=="mcl_bows:crossbow_1_enchanted" or stack:get_name()=="mcl_bows:crossbow_2_enchanted" then + stack:set_name("mcl_bows:crossbow_enchanted") + stack:get_meta():set_string("active", "") + list[place] = stack + end + end + inv:set_list("main", list) +end + +-- Resets the bow charging state and player speed. To be used when the player is no longer charging the bow +local function reset_bow_state(player, also_reset_bows) + bow_load[player:get_player_name()] = nil + bow_index[player:get_player_name()] = nil + if minetest.get_modpath("playerphysics") then + playerphysics.remove_physics_factor(player, "speed", "mcl_bows:use_crossbow") + end + if also_reset_bows then + reset_bows(player) + end +end + +-- Bow in charging state +for level=0, 2 do + minetest.register_tool("mcl_bows:crossbow_"..level, { + description = S("Crossbow"), + _doc_items_create_entry = false, + inventory_image = "mcl_bows_crossbow_"..level..".png", + wield_scale = mcl_vars.tool_wield_scale, + stack_max = 1, + range = 0, -- Pointing range to 0 to prevent punching with bow :D + groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, enchantability=1}, + -- Trick to disable digging as well + on_use = function() return end, + on_drop = function(itemstack, dropper, pos) + reset_bow_state(dropper) + itemstack:get_meta():set_string("active", "") + if mcl_enchanting.is_enchanted(itemstack:get_name()) then + itemstack:set_name("mcl_bows:crossbow_enchanted") + else + itemstack:set_name("mcl_bows:crossbow") + end + minetest.item_drop(itemstack, dropper, pos) + itemstack:take_item() + return itemstack + end, + -- Prevent accidental interaction with itemframes and other nodes + on_place = function(itemstack) + return itemstack + end, + _mcl_uses = 385, + }) +end + + +controls.register_on_release(function(player, key, time) + if key~="RMB" then return end + --local inv = minetest.get_inventory({type="player", name=player:get_player_name()}) + local wielditem = player:get_wielded_item() + if wielditem:get_name()=="mcl_bows:crossbow_2" and get_arrow(player) or wielditem:get_name()=="mcl_bows:crossbow_2" and minetest.is_creative_enabled(player:get_player_name()) or wielditem:get_name()=="mcl_bows:crossbow_2_enchanted" and get_arrow(player) or wielditem:get_name()=="mcl_bows:crossbow_2_enchanted" and minetest.is_creative_enabled(player:get_player_name()) then + local arrow_stack, arrow_stack_id = get_arrow(player) + local arrow_itemstring + + if minetest.is_creative_enabled(player:get_player_name()) then + if arrow_stack then + arrow_itemstring = arrow_stack:get_name() + else + arrow_itemstring = "mcl_bows:arrow" + end + else + arrow_itemstring = arrow_stack:get_name() + arrow_stack:take_item() + player:get_inventory():set_stack("main", arrow_stack_id, arrow_stack) + end + + wielditem:get_meta():set_string("arrow", arrow_itemstring) + + if wielditem:get_name()=="mcl_bows:crossbow_2" then + wielditem:set_name("mcl_bows:crossbow_loaded") + else + wielditem:set_name("mcl_bows:crossbow_loaded_enchanted") + end + player:set_wielded_item(wielditem) + minetest.sound_play("mcl_bows_crossbow_load", {pos=player:get_pos(), max_hear_distance=16}, true) + else + reset_bow_state(player, true) + end +end) + +controls.register_on_press(function(player, key, time) + if key~="LMB" then return end + wielditem = player:get_wielded_item() + if wielditem:get_name()=="mcl_bows:crossbow_loaded" or wielditem:get_name()=="mcl_bows:crossbow_loaded_enchanted" then + local enchanted = mcl_enchanting.is_enchanted(wielditem:get_name()) + local speed, damage + local p_load = bow_load[player:get_player_name()] + local charge + -- Type sanity check + if type(p_load) == "number" then + charge = minetest.get_us_time() - p_load + else + -- In case something goes wrong ... + -- Just assume minimum charge. + charge = 0 + minetest.log("warning", "[mcl_bows] Player "..player:get_player_name().." fires arrow with non-numeric bow_load!") + end + charge = math.max(math.min(charge, BOW_CHARGE_TIME_FULL), 0) + + local charge_ratio = charge / BOW_CHARGE_TIME_FULL + charge_ratio = math.max(math.min(charge_ratio, 1), 0) + + -- Calculate damage and speed + -- Fully charged + local is_critical = false + speed = BOW_MAX_SPEED + local r = math.random(1,5) + if r == 1 then + -- 20% chance for critical hit + damage = 10 + is_critical = true + else + damage = 9 + end + + local has_shot = player_shoot_arrow(wielditem, player, speed, damage, is_critical) + + if enchanted then + wielditem:set_name("mcl_bows:crossbow_enchanted") + else + wielditem:set_name("mcl_bows:crossbow") + end + + if has_shot and not minetest.is_creative_enabled(player:get_player_name()) then + local durability = BOW_DURABILITY + local unbreaking = mcl_enchanting.get_enchantment(wielditem, "unbreaking") + local multishot = mcl_enchanting.get_enchantment(wielditem, "multishot") + if unbreaking > 0 then + durability = durability * (unbreaking + 1) + end + if multishot then + durability = durability / 3 + end + wielditem:add_wear(65535/durability) + end + player:set_wielded_item(wielditem) + reset_bow_state(player, true) + end +end) + +controls.register_on_hold(function(player, key, time) + local name = player:get_player_name() + local creative = minetest.is_creative_enabled(name) + if key ~= "RMB" then + return + end + --local inv = minetest.get_inventory({type="player", name=name}) + local wielditem = player:get_wielded_item() + local enchantments = mcl_enchanting.get_enchantments(wielditem) + if enchantments.quick_charge then + BOW_CHARGE_TIME_HALF = _BOW_CHARGE_TIME_HALF - (enchantments.quick_charge * 0.13 * 1000000 * .5) + BOW_CHARGE_TIME_FULL = _BOW_CHARGE_TIME_FULL - (enchantments.quick_charge * 0.13 * 1000000) + else + BOW_CHARGE_TIME_HALF = _BOW_CHARGE_TIME_HALF + BOW_CHARGE_TIME_FULL = _BOW_CHARGE_TIME_FULL + end + + if bow_load[name] == nil and (wielditem:get_name()=="mcl_bows:crossbow" or wielditem:get_name()=="mcl_bows:crossbow_enchanted") and wielditem:get_meta():get("active") and (creative or get_arrow(player)) then + local enchanted = mcl_enchanting.is_enchanted(wielditem:get_name()) + if enchanted then + wielditem:set_name("mcl_bows:crossbow_0_enchanted") + play_load_sound(0, player:get_pos()) + else + wielditem:set_name("mcl_bows:crossbow_0") + play_load_sound(0, player:get_pos()) + end + player:set_wielded_item(wielditem) + if minetest.get_modpath("playerphysics") then + -- Slow player down when using bow + playerphysics.add_physics_factor(player, "speed", "mcl_bows:use_crossbow", PLAYER_USE_CROSSBOW_SPEED) + end + bow_load[name] = minetest.get_us_time() + bow_index[name] = player:get_wield_index() + else + if player:get_wield_index() == bow_index[name] then + if type(bow_load[name]) == "number" then + if wielditem:get_name() == "mcl_bows:crossbow_0" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_HALF then + wielditem:set_name("mcl_bows:crossbow_1") + play_load_sound(1, player:get_pos()) + elseif wielditem:get_name() == "mcl_bows:crossbow_0_enchanted" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_HALF then + wielditem:set_name("mcl_bows:crossbow_1_enchanted") + play_load_sound(1, player:get_pos()) + elseif wielditem:get_name() == "mcl_bows:crossbow_1" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_FULL then + wielditem:set_name("mcl_bows:crossbow_2") + play_load_sound(2, player:get_pos()) + elseif wielditem:get_name() == "mcl_bows:crossbow_1_enchanted" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_FULL then + wielditem:set_name("mcl_bows:crossbow_2_enchanted") + play_load_sound(2, player:get_pos()) + end + else + if wielditem:get_name() == "mcl_bows:crossbow_0" or wielditem:get_name() == "mcl_bows:crossbow_1" or wielditem:get_name() == "mcl_bows:crossbow_2" then + wielditem:set_name("mcl_bows:crossbow") + play_load_sound(1, player:get_pos()) + elseif wielditem:get_name() == "mcl_bows:crossbow_0_enchanted" or wielditem:get_name() == "mcl_bows:crossbow_1_enchanted" or wielditem:get_name() == "mcl_bows:crossbow_2_enchanted" then + wielditem:set_name("mcl_bows:crossbow_enchanted") + play_load_sound(1, player:get_pos()) + end + end + player:set_wielded_item(wielditem) + else + reset_bow_state(player, true) + end + end +end) + +minetest.register_globalstep(function(dtime) + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local wielditem = player:get_wielded_item() + local wieldindex = player:get_wield_index() + --local controls = player:get_player_control() + if type(bow_load[name]) == "number" and ((wielditem:get_name()~="mcl_bows:crossbow_0" and wielditem:get_name()~="mcl_bows:crossbow_1" and wielditem:get_name()~="mcl_bows:crossbow_2" and wielditem:get_name()~="mcl_bows:crossbow_0_enchanted" and wielditem:get_name()~="mcl_bows:crossbow_1_enchanted" and wielditem:get_name()~="mcl_bows:crossbow_2_enchanted") or wieldindex ~= bow_index[name]) then + reset_bow_state(player, true) + end + end +end) + +minetest.register_on_joinplayer(function(player) + reset_bows(player) +end) + +minetest.register_on_leaveplayer(function(player) + reset_bow_state(player, true) +end) + +if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then + minetest.register_craft({ + output = "mcl_bows:crossbow", + recipe = { + {"mcl_core:stick", "mcl_core:iron_ingot", "mcl_core:stick"}, + {"mcl_mobitems:string", "mcl_bows:arrow", "mcl_mobitems:string"}, + {"", "mcl_core:stick", ""}, + } + }) +end + +minetest.register_craft({ + type = "fuel", + recipe = "group:bow", + burntime = 15, +}) + +-- Add entry aliases for the Help +if minetest.get_modpath("doc") then + doc.add_entry_alias("tools", "mcl_bows:crossbow", "tools", "mcl_bows:crossbow_0") + doc.add_entry_alias("tools", "mcl_bows:crossbow", "tools", "mcl_bows:crossbow_1") + doc.add_entry_alias("tools", "mcl_bows:crossbow", "tools", "mcl_bows:crossbow_2") +end diff --git a/mods/ITEMS/mcl_bows/init.lua b/mods/ITEMS/mcl_bows/init.lua index a2745d950..d5b06dac7 100644 --- a/mods/ITEMS/mcl_bows/init.lua +++ b/mods/ITEMS/mcl_bows/init.lua @@ -1,5 +1,11 @@ +--Bow dofile(minetest.get_modpath("mcl_bows") .. "/arrow.lua") dofile(minetest.get_modpath("mcl_bows") .. "/bow.lua") +dofile(minetest.get_modpath("mcl_bows") .. "/rocket.lua") +--Crossbow +dofile(minetest.get_modpath("mcl_bows") .. "/crossbow.lua") + +--Compatiblility with older MineClone worlds minetest.register_alias("mcl_throwing:bow", "mcl_bows:bow") minetest.register_alias("mcl_throwing:arrow", "mcl_bows:arrow") diff --git a/mods/ITEMS/mcl_bows/models/mcl_bows_rocket.b3d b/mods/ITEMS/mcl_bows/models/mcl_bows_rocket.b3d new file mode 100644 index 0000000000000000000000000000000000000000..0a34f1eaa63c07c7f37e90df2300497fc6c5385f GIT binary patch literal 11758 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 SSLc+M3cN4yo ARROW_TIMEOUT then + self._stuck = true + end + if self._stuck then + if self._fuse > ARROW_TIMEOUT then + local eploded_particle = particle_explosion(self) + damage_explosion(self, eploded_particle * 17) + mcl_burning.extinguish(self.object) + self.object:remove() + return + end + -- Drop arrow as item when it is no longer stuck + -- FIXME: Arrows are a bit slow to react and continue to float in mid air for a few seconds. + if self._fuserechecktimer > STUCK_RECHECK_TIME then + local stuckin_def + if self._stuckin then + stuckin_def = minetest.registered_nodes[minetest.get_node(self._stuckin).name] + end + -- TODO: In MC, arrow just falls down without turning into an item + if stuckin_def and stuckin_def.walkable == false then + spawn_item(self, pos) + return + end + self._fuserechecktimer = 0 + end + -- Pickup arrow if player is nearby (not in Creative Mode) + local objects = minetest.get_objects_inside_radius(pos, 1) + for _,obj in ipairs(objects) do + if obj:is_player() then + if self._collectable and not minetest.is_creative_enabled(obj:get_player_name()) then + if obj:get_inventory():room_for_item("main", "mcl_bows:rocket") then + obj:get_inventory():add_item("main", "mcl_bows:rocket") + minetest.sound_play("item_drop_pickup", { + pos = pos, + max_hear_distance = 16, + gain = 1.0, + }, true) + end + end + mcl_burning.extinguish(self.object) + self.object:remove() + return + end + end + + -- Check for object "collision". Done every tick (hopefully this is not too stressing) + else + + if self._in_player == false then + minetest.add_particlespawner({ + amount = 1, + time = .0001, + minpos = pos, + maxpos = pos, + minvel = vector.new(-0.1,-0.1,-0.1), + maxvel = vector.new(0.1,0.1,0.1), + minexptime = 0.5, + maxexptime = 0.5, + minsize = 2, + maxsize = 2, + collisiondetection = false, + vertical = false, + texture = "mcl_bows_rocket_particle.png", + glow = 1, + }) + end + -- We just check for any hurtable objects nearby. + -- The radius of 3 is fairly liberal, but anything lower than than will cause + -- arrow to hilariously go through mobs often. + -- TODO: Implement an ACTUAL collision detection (engine support needed). + local objs = minetest.get_objects_inside_radius(pos, 1.5) + local closest_object + local closest_distance + + if self._deflection_cooloff > 0 then + self._deflection_cooloff = self._deflection_cooloff - dtime + end + + -- Iterate through all objects and remember the closest attackable object + for k, obj in pairs(objs) do + local ok = false + -- Arrows can only damage players and mobs + if obj:is_player() then + ok = true + elseif obj:get_luaentity() then + if (obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile) then + ok = true + end + end + + if ok then + local dist = vector.distance(pos, obj:get_pos()) + if not closest_object or not closest_distance then + closest_object = obj + closest_distance = dist + elseif dist < closest_distance then + closest_object = obj + closest_distance = dist + end + end + end + + -- If an attackable object was found, we will damage the closest one only + + if closest_object then + local obj = closest_object + local is_player = obj:is_player() + local lua = obj:get_luaentity() + if obj == self._shooter and self._time_in_air > 1.02 or obj ~= self._shooter and (is_player or (lua and (lua._cmi_is_mob or lua._hittable_by_projectile))) then + if obj:get_hp() > 0 then + -- Check if there is no solid node between arrow and object + local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true) + for pointed_thing in ray do + if pointed_thing.type == "object" and pointed_thing.ref == closest_object then + -- Target reached! We can proceed now. + break + elseif pointed_thing.type == "node" then + local nn = minetest.get_node(minetest.get_pointed_thing_position(pointed_thing)).name + local def = minetest.registered_nodes[nn] + if (not def) or def.walkable then + -- There's a node in the way. Delete arrow without damage + mcl_burning.extinguish(self.object) + self.object:remove() + return + end + end + end + + -- Punch target object but avoid hurting enderman. + if not lua or lua.name ~= "mobs_mc:enderman" then + if self._in_player == false then + damage_particles(self.object:get_pos(), self._is_critical) + end + if mcl_burning.is_burning(self.object) then + mcl_burning.set_on_fire(obj, 5) + end + if self._in_player == false then + obj:punch(self.object, 1.0, { + full_punch_interval=1.0, + damage_groups={fleshy=self._damage}, + }, self.object:get_velocity()) + if obj:is_player() then + local eploded_particle = particle_explosion(self) + damage_explosion(self, eploded_particle * 17) + mcl_burning.extinguish(self.object) + self.object:remove() + end + end + end + + + if is_player then + if self._shooter and self._shooter:is_player() and self._in_player == false then + -- “Ding” sound for hitting another player + minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter:get_player_name()}, true) + end + end + + if lua then + local entity_name = lua.name + -- Achievement for hitting skeleton, wither skeleton or stray (TODO) with an arrow at least 50 meters away + -- NOTE: Range has been reduced because mobs unload much earlier than that ... >_> + -- TODO: This achievement should be given for the kill, not just a hit + if self._shooter and self._shooter:is_player() and vector.distance(pos, self._startpos) >= 20 then + if mod_awards and (entity_name == "mobs_mc:skeleton" or entity_name == "mobs_mc:stray" or entity_name == "mobs_mc:witherskeleton") then + awards.unlock(self._shooter:get_player_name(), "mcl:snipeSkeleton") + end + end + end + if self._in_player == false then + minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true) + end + end + if not obj:is_player() then + mcl_burning.extinguish(self.object) + if self._piercing == 0 then + local eploded_particle = particle_explosion(self) + damage_explosion(self, eploded_particle * 17) + self.object:remove() + end + end + return + end + end + end + + -- Check for node collision + if self._lastpos.x~=nil and not self._stuck then + local def = minetest.registered_nodes[node.name] + local vel = self.object:get_velocity() + -- Arrow has stopped in one axis, so it probably hit something. + -- This detection is a bit clunky, but sadly, MT does not offer a direct collision detection for us. :-( + if (math.abs(vel.x) < 0.0001) or (math.abs(vel.z) < 0.0001) or (math.abs(vel.y) < 0.00001) then + -- Check for the node to which the arrow is pointing + local dir + if math.abs(vel.y) < 0.00001 then + if self._lastpos.y < pos.y then + dir = {x=0, y=1, z=0} + else + dir = {x=0, y=-1, z=0} + end + else + dir = minetest.facedir_to_dir(minetest.dir_to_facedir(minetest.yaw_to_dir(self.object:get_yaw()-YAW_OFFSET))) + end + self._stuckin = vector.add(dpos, dir) + local snode = minetest.get_node(self._stuckin) + local sdef = minetest.registered_nodes[snode.name] + + -- If node is non-walkable, unknown or ignore, don't make arrow stuck. + -- This causes a deflection in the engine. + if not sdef or sdef.walkable == false or snode.name == "ignore" then + self._stuckin = nil + if self._deflection_cooloff <= 0 then + -- Lose 1/3 of velocity on deflection + local newvel = vector.multiply(vel, 0.6667) + + self.object:set_velocity(newvel) + -- Reset deflection cooloff timer to prevent many deflections happening in quick succession + self._deflection_cooloff = 1.0 + end + else + + -- Node was walkable, make arrow stuck + self._stuck = true + self._fuserechecktimer = 0 + + self.object:set_velocity({x=0, y=0, z=0}) + self.object:set_acceleration({x=0, y=0, z=0}) + + minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true) + + if mcl_burning.is_burning(self.object) and snode.name == "mcl_tnt:tnt" then + tnt.ignite(self._stuckin) + end + + -- Push the button! Push, push, push the button! + if mod_button and minetest.get_item_group(node.name, "button") > 0 and minetest.get_item_group(node.name, "button_push_by_arrow") == 1 then + local bdir = minetest.wallmounted_to_dir(node.param2) + -- Check the button orientation + if vector.equals(vector.add(dpos, bdir), self._stuckin) then + mesecon.push_button(dpos, node) + end + end + end + elseif (def and def.liquidtype ~= "none") then + -- Slow down arrow in liquids + local v = def.liquid_viscosity + if not v then + v = 0 + end + --local old_v = self._viscosity + self._viscosity = v + local vpenalty = math.max(0.1, 0.98 - 0.1 * v) + if math.abs(vel.x) > 0.001 then + vel.x = vel.x * vpenalty + end + if math.abs(vel.z) > 0.001 then + vel.z = vel.z * vpenalty + end + self.object:set_velocity(vel) + end + end + + -- Update yaw + if not self._stuck then + local vel = self.object:get_velocity() + local yaw = minetest.dir_to_yaw(vel)+YAW_OFFSET + local pitch = dir_to_pitch(vel) + self.object:set_rotation({ x = 0, y = yaw, z = pitch }) + end + + -- Update internal variable + self._lastpos={x=pos.x, y=pos.y, z=pos.z} +end + +-- Force recheck of stuck arrows when punched. +-- Otherwise, punching has no effect. +function ARROW_ENTITY.on_punch(self) + if self._stuck then + self._fuserechecktimer = STUCK_RECHECK_TIME + end +end + +function ARROW_ENTITY.get_staticdata(self) + local out = { + lastpos = self._lastpos, + startpos = self._startpos, + damage = self._damage, + is_critical = self._is_critical, + stuck = self._stuck, + stuckin = self._stuckin, + } + if self._stuck then + -- If _fuse is missing for some reason, assume the maximum + if not self._fuse then + self._fuse = ARROW_TIMEOUT + end + out.stuckstarttime = minetest.get_gametime() - self._fuse + end + if self._shooter and self._shooter:is_player() then + out.shootername = self._shooter:get_player_name() + end + return minetest.serialize(out) +end + +function ARROW_ENTITY.on_activate(self, staticdata, dtime_s) + self._time_in_air = 1.0 + self._in_player = false + local data = minetest.deserialize(staticdata) + if data then + self._stuck = data.stuck + if data.stuck then + if data.stuckstarttime then + -- First, check if the stuck arrow is aleady past its life timer. + -- If yes, delete it. + self._fuse = minetest.get_gametime() - data.stuckstarttime + if self._fuse > ARROW_TIMEOUT then + mcl_burning.extinguish(self.object) + self.object:remove() + return + end + end + + self._fuse = 2 + -- Perform a stuck recheck on the next step. + self._fuserechecktimer = STUCK_RECHECK_TIME + + self._stuckin = data.stuckin + end + + -- Get the remaining arrow state + self._lastpos = data.lastpos + self._startpos = data.startpos + self._damage = data.damage + self._is_critical = data.is_critical + if data.shootername then + local shooter = minetest.get_player_by_name(data.shootername) + if shooter and shooter:is_player() then + self._shooter = shooter + end + end + end + self.object:set_armor_groups({ immortal = 1 }) +end + +minetest.register_entity("mcl_bows:rocket_entity", ARROW_ENTITY) + +if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then + minetest.register_craft({ + output = "mcl_bows:rocket 1", + recipe = { + {"mcl_core:paper"}, + {"mcl_fireworks:rocket_2"}, + {"mcl_bows:arrow"}, + } + }) +end + +if minetest.get_modpath("doc_identifier") then + doc.sub.identifier.register_object("mcl_bows:rocket_entity", "craftitems", "mcl_bows:rocket") +end diff --git a/mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_drawback_0.ogg b/mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_drawback_0.ogg new file mode 100644 index 0000000000000000000000000000000000000000..f4f81b30749b453245ee3b3280244ceecb167fe0 GIT binary patch literal 13529 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 e*8{%PUj#&N^p*&fe$j&)LK0>~moC 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 literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_shoot.ogg b/mods/ITEMS/mcl_bows/sounds/mcl_bows_crossbow_shoot.ogg new file mode 100644 index 0000000000000000000000000000000000000000..a7d7b69d12fdd3ff614c0c612faa7a2d03f40459 GIT binary patch literal 9767 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 literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_1.png b/mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_1.png new file mode 100644 index 0000000000000000000000000000000000000000..3769f2967b880e0b3eaa1162b8db067891f48b19 GIT binary patch literal 2383 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 literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_3.png b/mods/ITEMS/mcl_bows/textures/mcl_bows_crossbow_3.png new file mode 100644 index 0000000000000000000000000000000000000000..8a8f1b03fcfaf94a5ef572da591dc05a5c80080f GIT binary patch literal 2794 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 QCIA2c07*qoM6N<$f>%QorT_o{ literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_bows/textures/mcl_bows_firework_green.png b/mods/ITEMS/mcl_bows/textures/mcl_bows_firework_green.png new file mode 100644 index 0000000000000000000000000000000000000000..acd74d6d1c59b86acfa3c74c9861a414b28f061c GIT binary patch literal 627 zcmV-(0*w8MP)EX>4Tx04R}tkv&MmKpe$iTSX}?4pxxj5U@H~5EXIMDionYs1;guFuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|=H{g6A|?JWDYS_3;J6>}?mh0_0scmXsb<$WplX(p zP9}tGZdK@cMG#>OU>H$}nfjb4rrU7TlmpZjx!mAuISpFljzbi*RvAfDc| zbk6(45mu5E;&b9LgDyz?$aUG}H_kbWYY7*5n`d(!Ey()lA#h$5yuo&qkMnX zWrgz=XSGset$XqphVt6VGS_JiA&EsSL4*JqHIz|-g*dGmDJIgipYZTU9luB}nOtQs zax9<<6_Voz|AXJ%nuW;;Hz||=x?gPjV+82g1)6o+{yw(t<_QpZ2ClTWzuEw1K1r{) zwb&8Rw+&oew>5bWxZD8-pLEHP94SE4Unl_YXY@@up#K&KuDQLn_Hp_EWT>mu4RCM> zj20<--Q(T8oxS~grq$mMb0c!6Z+X|p00009a7bBm000XU000XU0RWnu7ytkO2XskI zMF-^y4HYOI7BNEw0001jNklYzcxul;3SeR&5wJig1tv8yW=TBiUj2Rk;NLBT z1~FzyOHM~2W>KuF-~D}k{QG_s4GatnLd>G_?8+>RtZ1tL{Qu4H6T?YR4kIfwBQupf zJsdQ!pobs^Koev^jveIiMvFLf4X^$_KmL6`{-lAT;laOKkeH{wrvVGvFD=Wy1!MpK N002ovPDHLkV1m_i4Y~jT literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_bows/textures/mcl_bows_firework_red.png b/mods/ITEMS/mcl_bows/textures/mcl_bows_firework_red.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7355c57a57e45bcf3060f4831604a1bc07d10a GIT binary patch literal 622 zcmV-!0+IcRP)EX>4Tx04R}tkv&MmKpe$iTSX}?4pxxj5U@H~5EXIMDionYs1;guFuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|=H{g6A|?JWDYS_3;J6>}?mh0_0scmXsb<$WplX(p zP9}tGZdK@cMG#>OU>H$}nfjb4rrU7TlmpZjx!mAuISpFljzbi*RvAfDc| zbk6(45mu5E;&b9LgDyz?$aUG}H_kbWYY7*5n`d(!Ey()lA#h$5yuo&qkMnX zWrgz=XSGset$XqphVt6VGS_JiA&EsSL4*JqHIz|-g*dGmDJIgipYZTU9luB}nOtQs zax9<<6_Voz|AXJ%nuW;;Hz||=x?gPjV+82g1)6o+{yw(t<_QpZ2ClTWzuEw1K1r{) zwb&8Rw+&oew>5bWxZD8-pLEHP94SE4Unl_YXY@@up#K&KuDQLn_Hp_EWT>mu4RCM> zj20<--Q(T8oxS~grq$mMb0c!6Z+X|p00009a7bBm000XU000XU0RWnu7ytkO2XskI zMF-^y4HYO23x-o+0001eNklYjYH!a#3SeR&5wJk@si`qbO5#!X_xbaGw{9Uc zFiT2uIyy3oiegv&`t|qy`%yG7FfcHSin1#!GqSRxss8`__fJeGK>#BwD zaB^>EX>4U6ba`-PAZ2)IW&i+q+TB-Mmg6W4{nsjH2}nXbmV?2Z(>v(p&&4*bI92IN zI`uJULfMjKA;i5PT(tiF)#)Gn#IcaKm_iQ0;pel@QlKQa|MGTc=ePUu;HGl1)A<5n zokHsV7|Y>bV7HGBa|~Xtc1p(^Nk^a=`3R_EWP#FdlZ0J%JNqM0UUwzr6mL^qWS8}D z+)_C%ja%q5$atn(gO5O|8N5_vRaUp%)1HBji?s~CnMleQ~hmHR9@|8xt*8vf` zbYg|PWUO4IF_;^7c!3b^2XD3kJljFPyIDV2s$kGIm=h*g+_HyQj6c?vZagde407KU zOtBpS01?JEB*O{@Twpa0?4n3y295~?6=W{h8w(g=xfG#-feK<3_!n3fS#En$gETJlmVmQVH7YN)ZMnrms& zw4qG2&|*t1x3V&=s1&PTZ4GN&)0)@PvDUhF->rupd+NEDleL4@PwfTP_+U*oriNcU zS%Z~goFRCW6C0d?G4Tw><6r;_S_Wq>vG+2V8=Sc;*c2v6(gruwcrXSE{mNpUPwqaL zdx|%*^b~LM9dk6O`w8X<)P3gd3)b2==jz7Tz6%GYPOqvPyOB}Pn z$B~>6F+B%GK6;v;QF)z7t(%D+bEAGvpruLIIwLPfWS)}l4R=x|8UD;5&Veqd(6g}Q z&#+u1eGiL1g5`n+y#dQb(i^Z`B)tL4MbaCvTqL~#%SF-~uv}1~H(0dQdoLY*vb#nj!0flKpLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ#a~mUQd%7> z_<=))>SRGw#8InIgbJlrXw|{w(hs3YLz3d+D7Y3J{8+3yxH#+T;3^1$A0TdSPKqv4 z;{TFDix>}%`|XH%&pJjd5P ze0;r&@htCie~z${HyPj)iD#H@Sj6kZQ=68~d7n7KN|Hi+PCRPR1&JTIF1!53x#+OK zGb2VOJx3fN7K?2xw=pXjD)A(7R8cj`7qTuZoVPfu%gm2FkDyqg5ltM4I;F9{xecpCXq`t_?79%%cJolH&*egWuhng^6)DDHI1fUu^qh z7zpeFjhbzLAKP~01n@rtS6a(osRPrWq}N(n^a$wL1}?5!n!E>G?g0Hyx@1U>MD5y92^28Mao|Dcz0KOZ~vZY_V)upL2{ECAdxKq z000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jvP57Y-u@zorTR004DKL_t(2&)t$e z4uBvGgZ%TyO0aUeK b{`;X<* zaB^>EX>4U6ba`-PAZ2)IW&i+q+Ray4lI$o9{MRYw2uL6h$H6QSbAvhlB;Z=Qt9q&K z_wkCbk!2x?OaU(H|NT4YAN+(xC}^^nV|4h19I_M$=JqeIJG-#%=YzWlZ}fD1Ay9er zem|yi+85~cHsBJ2kGFcV^NrZ)=;HZw=x1bs(C(9jUbddY=_vOt#BAw4)kAh)Ps5eU zdHJ+lU!BZnx>tk*l$yfIi*(Q4t-I|E{JhwgsbBX1JN9wOp3nt-o5|;>0vtOHAb^B`kq}05s1dK zq8we&nPXsh0CK;EMYM!VA*aa%U2qWQ71&~ z?1~lgl3BS(V=_1IumT}GPTq6@d}$~B?yi1Ns$ftT%!UaTcWf7j@~yV~;@QJa(eG8k zl-lV45FxfA8TMenMfS>(T@p#mz|lZZLFR(Baex6Fw{^{uR&F#CNrp{ya^?~q0Rz^jOLGWZ{9&kVE$^Fv7 zU*zaWK^dPQD3=_?Xlgq)fZrxY7om(Dz~`u8s^qZH?4xnbZ<`iE!>Y+A*M zv&`K~Ju<>N+uohjnzvZ799*rphwxQuv~z1`qRnS_v^`1XY<=mA1zx)O;qpOGr{Lp? zkQt}&lDcA>b!ExJSwFnrNel@+KhAE0?XdQ@m0HJA-@Zl)9m{=>@6`)$eSDS|Jxx?} zN#^P}39KztIUy5Y>H~iCHMjTpwUZZ|=cY@{=2ld~PPxN>+~<`i_E5j)-?1}3z(=3p z_Y!>c34SlZN1x#L5`6RtelNjCpWycreDt&Od+h0F<@X35{jB^R;i8|F-y?kV?edec zLTL*T|6`WE@GTAcg5Nz;eB~?eY2xpbdxjsqQh)LG@USz}i(B)DJ2QQAYkqf%Jsx88 zyVLA;h|#xBv2XPBC(ix9$kD(DSVmR<4>_^-vPu8QtpET4g=s@WP)S2WAaHVTW@&6? z004NLeUUv#!$2IxUsI)0S{*F-fkTGsWIiY`*(|B^zB7!Qv7@$TN^?j0c1%S<&p#sF2bjC3L{W^*fI z;1xl1qYq&WNX*n{Q>i38$Jaf4e7%eDEbnuFjF%XP9nS#OuUUo0iUbpE$xw zl0tk=JZjJdi66NxyZpwv=&-;uBSt1YM;sv*i)}2oF)JA=@g#9nQ8mgJvMwu}w>Yci zDr?@8zc7^7mY29ra|j76U=b;ZkWs}3%CHclRU^ejn)c%!{z1o|B9~0A4KQ-dqXHF@ z;|KqP-`$#piE%e66bCwAZ2Myv2@ApqkCqV!s6DuPlGk$N9?CIg4fdwrD zF-`dY?>BZ0e}BIIi8GpCqigv4^ZEBT`|&3Y6b=8r-GanC^*s#$Sz#~>;{u0_00000 LNkvXXu0mjfC5$>B literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_bows/textures/mcl_bows_rocket.png b/mods/ITEMS/mcl_bows/textures/mcl_bows_rocket.png new file mode 100644 index 0000000000000000000000000000000000000000..800185ce08db4e4327442dcee0a0393223ad1bc5 GIT binary patch literal 2133 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 FV1hj1Dy9Gc literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_enchanting/enchantments.lua b/mods/ITEMS/mcl_enchanting/enchantments.lua index ecc9fe113..17b6b6ac6 100644 --- a/mods/ITEMS/mcl_enchanting/enchantments.lua +++ b/mods/ITEMS/mcl_enchanting/enchantments.lua @@ -379,8 +379,8 @@ mcl_enchanting.enchantments.mending = { inv_tool_tab = true, } --- requires missing MineClone2 feature ---[[mcl_enchanting.enchantments.multishot = { + +mcl_enchanting.enchantments.multishot = { name = S("Multishot"), max_level = 1, primary = {crossbow = true}, @@ -396,10 +396,10 @@ mcl_enchanting.enchantments.mending = { power_range_table = {{20, 50}}, inv_combat_tab = true, inv_tool_tab = false, -}]]-- +} -- requires missing MineClone2 feature ---[[mcl_enchanting.enchantments.piercing = { +mcl_enchanting.enchantments.piercing = { name = S("Piercing"), max_level = 4, primary = {crossbow = true}, @@ -415,7 +415,7 @@ mcl_enchanting.enchantments.mending = { power_range_table = {{1, 50}, {11, 50}, {21, 50}, {31, 50}}, inv_combat_tab = true, inv_tool_tab = false, -}]]-- +} -- implemented in mcl_bows mcl_enchanting.enchantments.power = { @@ -456,7 +456,7 @@ mcl_enchanting.enchantments.punch = { } -- requires missing MineClone2 feature ---[[mcl_enchanting.enchantments.quick_charge = { +mcl_enchanting.enchantments.quick_charge = { name = S("Quick Charge"), max_level = 3, primary = {crossbow = true}, @@ -472,7 +472,7 @@ mcl_enchanting.enchantments.punch = { power_range_table = {{12, 50}, {32, 50}, {52, 50}}, inv_combat_tab = true, inv_tool_tab = false, -}]]-- +} -- unimplemented --[[mcl_enchanting.enchantments.respiration = { diff --git a/mods/ITEMS/mcl_mobspawners/init.lua b/mods/ITEMS/mcl_mobspawners/init.lua index 6c5d7f6e4..b756d4a6d 100644 --- a/mods/ITEMS/mcl_mobspawners/init.lua +++ b/mods/ITEMS/mcl_mobspawners/init.lua @@ -230,7 +230,7 @@ local function spawn_mobs(pos, elapsed) -- spawn up to 4 mobs in random air blocks if air then - local max = 4 + local max = 200 if spawn_count_overrides[mob] then max = spawn_count_overrides[mob] end @@ -387,4 +387,3 @@ minetest.register_lbm({ respawn_doll(pos) end, }) - diff --git a/mods/ITEMS/mcl_potions/tipped_arrow.lua b/mods/ITEMS/mcl_potions/tipped_arrow.lua index ab55cb72a..1717533a8 100644 --- a/mods/ITEMS/mcl_potions/tipped_arrow.lua +++ b/mods/ITEMS/mcl_potions/tipped_arrow.lua @@ -463,4 +463,4 @@ function mcl_potions.register_arrow(name, desc, color, def) if minetest.get_modpath("doc_identifier") then doc.sub.identifier.register_object("mcl_bows:arrow_entity", "craftitems", "mcl_bows:arrow") end -end \ No newline at end of file +end diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index a3c769741..2a4c25c34 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -9,7 +9,7 @@ local animation_blend = 0 local function get_mouse_button(player) local controls = player:get_player_control() local get_wielded_item_name = player:get_wielded_item():get_name() - if controls.RMB and not string.find(get_wielded_item_name, "mcl_bows:bow") or controls.LMB then + if controls.RMB and not string.find(get_wielded_item_name, "mcl_bows:bow") and not string.find(get_wielded_item_name, "mcl_bows:crossbow") or controls.LMB then return true else return false @@ -212,9 +212,9 @@ minetest.register_globalstep(function(dtime) player_set_animation(player, "swim_walk_mine", animation_speed_mod) elseif not controls.sneak and head_in_water and is_sprinting == true then player_set_animation(player, "swim_walk", animation_speed_mod) - elseif string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB and controls.sneak then + elseif string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB and controls.sneak or string.find(player:get_wielded_item():get_name(), "mcl_bows:crossbow_") and controls.sneak then player_set_animation(player, "bow_sneak", animation_speed_mod) - elseif string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB then + elseif string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB or string.find(player:get_wielded_item():get_name(), "mcl_bows:crossbow_") then player_set_animation(player, "bow_walk", animation_speed_mod) elseif is_sprinting == true and get_mouse_button(player) == true and not controls.sneak and not head_in_water then player_set_animation(player, "run_walk_mine", animation_speed_mod) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 1f881d2b6..f86d5e26a 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -127,6 +127,7 @@ minetest.register_globalstep(function(dtime) for _,player in pairs(get_connected_players()) do --[[ + _ _ _ __ _ _ __ (_)_ __ ___ __ _| |_(_) ___ _ __ ___ / _` | '_ \| | '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| @@ -220,6 +221,10 @@ minetest.register_globalstep(function(dtime) player:set_bone_position("Wield_Item", vector.new(0,3.9,1.3), vector.new(90,0,0)) elseif string.find(wielded:get_name(), "mcl_bows:bow") then player:set_bone_position("Wield_Item", vector.new(.5,4.5,-1.6), vector.new(90,0,20)) + elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then + player:set_bone_position("Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(64,90,0)) + elseif string.find(wielded:get_name(), "mcl_bows:crossbow") then + player:set_bone_position("Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(90,90,0)) else player:set_bone_position("Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90)) end @@ -231,6 +236,14 @@ minetest.register_globalstep(function(dtime) if string.find(wielded:get_name(), "mcl_bows:bow") and control.RMB then player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35)) player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35)) + -- controls right and left arms pitch when holing a loaded crossbow + elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then + player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35)) + player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35)) + -- controls right and left arms pitch when loading a crossbow + elseif string.find(wielded:get_name(), "mcl_bows:crossbow_") then + player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(45,-20,25)) + player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(55,20,-45)) -- when punching elseif control.LMB and not parent then player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch,0,0))