From 4c8efca4e6fb89b8ae3227f85c691437d7df2f3a Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Mon, 15 Jan 2024 05:45:44 +0000 Subject: [PATCH 01/19] Add eating delay code --- mods/PLAYER/mcl_hunger/init.lua | 152 ++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/mods/PLAYER/mcl_hunger/init.lua b/mods/PLAYER/mcl_hunger/init.lua index ff625a5f7..ddc771e4a 100644 --- a/mods/PLAYER/mcl_hunger/init.lua +++ b/mods/PLAYER/mcl_hunger/init.lua @@ -30,6 +30,10 @@ mcl_hunger.EXHAUST_REGEN = 6000 -- Regenerate 1 HP mcl_hunger.EXHAUST_HUNGER = 5 -- Hunger status effect at base level. mcl_hunger.EXHAUST_LVL = 4000 -- at what exhaustion player saturation gets lowered +mcl_hunger.EATING_DELAY = tonumber(minetest.settings:get("mcl_eating_delay")) or 1.61 +mcl_hunger.EATING_WALK_SPEED = tonumber(minetest.settings:get("movement_speed_crouch")) / tonumber(minetest.settings:get("movement_speed_walk")) +mcl_hunger.EATING_TOUCHSCREEN_DELAY_PADDING = 0.75 + mcl_hunger.SATURATION_INIT = 5 -- Initial saturation for new/respawning players -- Debug Mode. If enabled, saturation and exhaustion are shown as well. @@ -39,6 +43,39 @@ mcl_hunger.debug = false -- Cooldown timers for each player, to force a short delay between consuming 2 food items mcl_hunger.last_eat = {} +-- Variables for each player, to handle delayed eating +mcl_hunger.eat_internal = {} + +-- Set per player internal variables for delayed eating +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + + mcl_hunger.eat_internal[name] = { + is_eating = false, + itemname = nil, + item_definition = nil, + hp_change = nil, + replace_with_item = nil, + itemstack = nil, + user = nil, + pointed_thing = nil, + pitch = nil, + do_item_eat = false, + _custom_itemstack = nil, -- Used as comparison to make sure _custom_wrapper only executes when the same item is eaten + _custom_var = {}, -- Variables that can be used by _custom_var and _custom_wrapper + _custom_func = nil, -- Can be executed by _custom_wrapper + _custom_wrapper = nil, -- Will execute alongside minetest.do_item_eat if not empty and _custom_itemstack is equal to current player itemstack + _custom_do_delayed = false, -- If true, then will execute only _custom_wrapper after holding RMB or LMB within a delay specified by mcl_hunger.EATING_DELAY (Use to bypass minetest.do_item_eat entirely) + } +end) + +-- Clear when player leaves +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + + mcl_hunger.eat_internal[name] = nil +end) + dofile(modpath.."/api.lua") dofile(modpath.."/hunger.lua") dofile(modpath.."/register_foods.lua") @@ -138,6 +175,34 @@ minetest.register_on_player_hpchange(function(player, hp_change) end) local food_tick_timers = {} -- one food_tick_timer per player, keys are the player-objects +local eat_start_timers = {} +local eat_tick_timers = {} +local eat_effects_cooldown = {} + +local function clear_eat_internal_and_timers(player, player_name) + playerphysics.remove_physics_factor(player, "speed", "mcl_hunger:eating_speed") + mcl_hunger.eat_internal[player_name] = { + is_eating = false, + itemname = nil, + item_definition = nil, + hp_change = nil, + replace_with_item = nil, + itemstack = nil, + user = nil, + pointed_thing = nil, + pitch = nil, + do_item_eat = false, + _custom_itemstack = nil, + _custom_var = {}, + _custom_func = nil, + _custom_wrapper = nil, + _custom_do_delayed = false, + } + eat_start_timers[player] = 0 + eat_tick_timers[player] = 0 + eat_effects_cooldown[player] = 0 +end + minetest.register_globalstep(function(dtime) for _,player in pairs(minetest.get_connected_players()) do @@ -184,6 +249,93 @@ minetest.register_globalstep(function(dtime) end food_tick_timers[player] = food_tick_timer -- update food_tick_timer table + + -- Eating delay code + if mcl_hunger.eat_internal[player_name].is_eating or mcl_hunger.eat_internal[player_name]._custom_do_delayed then + local control = player:get_player_control() + local inv = player:get_inventory() + local current_itemstack = player:get_wielded_item() + + if not eat_start_timers[player] then + eat_start_timers[player] = 0 + end + + eat_start_timers[player] = eat_start_timers[player] + dtime + + if not eat_tick_timers[player] then + eat_tick_timers[player] = 0 + end + + if not eat_effects_cooldown[player] then + eat_effects_cooldown[player] = 0 + end + + if not mcl_hunger.eat_internal[player_name].pitch then + mcl_hunger.eat_internal[player_name].pitch = 1 + math.random(-10, 10)*0.005 + end + + -- check if holding RMB (or LMB as workaround for touchscreen) + if (current_itemstack == mcl_hunger.eat_internal[player_name].itemstack or current_itemstack == mcl_hunger.eat_internal[player_name]._custom_itemstack) and (control.RMB or control.LMB) then + eat_tick_timers[player] = eat_tick_timers[player] + dtime + eat_effects_cooldown[player] = eat_effects_cooldown[player] + dtime + + playerphysics.add_physics_factor(player, "speed", "mcl_hunger:eating_speed", mcl_hunger.EATING_WALK_SPEED) + + if eat_effects_cooldown[player] > 0.2 then + eat_effects_cooldown[player] = 0 + + local pos = player:get_pos() + local itemname = mcl_hunger.eat_internal[player_name].itemname + local def = minetest.registered_items[itemname] + + mcl_hunger.eat_effects( + mcl_hunger.eat_internal[player_name].user, + mcl_hunger.eat_internal[player_name].itemname, + pos, + mcl_hunger.eat_internal[player_name].hp_change, + def, + mcl_hunger.eat_internal[player_name].pitch + ) + end + + -- check if eating delay is over + if eat_tick_timers[player] >= mcl_hunger.EATING_DELAY then + + if not mcl_hunger.eat_internal[player_name]._custom_do_delayed then + mcl_hunger.eat_internal[player_name].do_item_eat = true + + minetest.do_item_eat( + mcl_hunger.eat_internal[player_name].hp_change, + mcl_hunger.eat_internal[player_name].replace_with_item, + mcl_hunger.eat_internal[player_name].itemstack, + mcl_hunger.eat_internal[player_name].user, + mcl_hunger.eat_internal[player_name].pointed_thing + ) + + -- bypass minetest.do_item_eat and only execute _custom_wrapper + elseif mcl_hunger.eat_internal[player_name]._custom_itemstack and + mcl_hunger.eat_internal[player_name]._custom_wrapper and + mcl_hunger.eat_internal[player_name]._custom_itemstack == current_itemstack then + + mcl_hunger.eat_internal[player_name]._custom_wrapper(player_name) + + player:get_inventory():set_stack("main", player:get_wield_index(), itemstack) + end + + clear_eat_internal_and_timers(player, player_name) + end + + elseif eat_start_timers[player] and eat_start_timers[player] > 0.2 then + playerphysics.remove_physics_factor(player, "speed", "mcl_hunger:eating_speed") + + elseif eat_start_timers[player] and eat_start_timers[player] > mcl_hunger.EATING_TOUCHSCREEN_DELAY_PADDING then + clear_eat_internal_and_timers(player, player_name) + end + end + + if eat_start_timers[player] and eat_start_timers[player] > mcl_hunger.EATING_DELAY + mcl_hunger.EATING_TOUCHSCREEN_DELAY_PADDING then + clear_eat_internal_and_timers(player, player_name) + end end end) From 996a5a6d47db7426998555a897b23df63cf25c6f Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Mon, 15 Jan 2024 05:56:24 +0000 Subject: [PATCH 02/19] Integrate delayed eating to item eat code --- mods/PLAYER/mcl_hunger/hunger.lua | 120 +++++++++++++++++++----------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index d9a6fd5fe..623d459f9 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -38,7 +38,23 @@ function minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, poi local can_eat_when_full = creative or (mcl_hunger.active == false) or minetest.get_item_group(itemstack:get_name(), "can_eat_when_full") == 1 -- Don't allow eating when player has full hunger bar (some exceptional items apply) - if can_eat_when_full or (mcl_hunger.get_hunger(user) < 20) then + if not no_eat_delay and not mcl_hunger.eat_internal[name].is_eating and not mcl_hunger.eat_internal[name].do_item_eat and (can_eat_when_full or (mcl_hunger.get_hunger(user) < 20)) then + local itemname = itemstack:get_name() + mcl_hunger.eat_internal[name].is_eating = true + mcl_hunger.eat_internal[name].itemname = itemname + mcl_hunger.eat_internal[name].item_definition = minetest.registered_items[itemname] + mcl_hunger.eat_internal[name].hp_change = hp_change + mcl_hunger.eat_internal[name].replace_with_item = replace_with_item + mcl_hunger.eat_internal[name].itemstack = itemstack + mcl_hunger.eat_internal[name].user = user + mcl_hunger.eat_internal[name].pointed_thing = pointed_thing + elseif (mcl_hunger.eat_internal[name].do_item_eat or no_eat_delay) and (can_eat_when_full or (mcl_hunger.get_hunger(user) < 20)) then + if mcl_hunger.eat_internal[name]._custom_itemstack and + mcl_hunger.eat_internal[name]._custom_wrapper and + mcl_hunger.eat_internal[name]._custom_itemstack == itemstack then + + mcl_hunger.eat_internal[name]._custom_wrapper(name) + end itemstack = mcl_hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing) for _, callback in pairs(minetest.registered_on_item_eats) do local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack) @@ -47,6 +63,7 @@ function minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, poi end end mcl_hunger.last_eat[name] = os.time() + user:get_inventory():set_stack("main", user:get_wield_index(), itemstack) end end @@ -129,49 +146,9 @@ function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poiso --local hp = user:get_hp() local pos = user:get_pos() - -- player height - pos.y = pos.y + 1.5 - local foodtype = minetest.get_item_group(itemname, "food") - if foodtype == 3 then - -- Item is a drink, only play drinking sound (no particle) - minetest.sound_play("survival_thirst_drink", { - max_hear_distance = 12, - gain = 1.0, - pitch = 1 + math.random(-10, 10)*0.005, - object = user, - }, true) - else - -- Assume the item is a food - -- Add eat particle effect and sound - local def = minetest.registered_items[itemname] - local texture = def.inventory_image - if not texture or texture == "" then - texture = def.wield_image - end - -- Special item definition field: _food_particles - -- 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() - 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, - gain = 1.0, - pitch = 1 + math.random(-10, 10)*0.005, - object = user, - }, true) - end + local def = minetest.registered_items[itemname] + + mcl_hunger.eat_effects(user, itemname, pos, hunger_change, def) if mcl_hunger.active and hunger_change then -- Add saturation (must be defined in item table) @@ -226,6 +203,61 @@ function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poiso end end +function mcl_hunger.eat_effects(user, itemname, pos, hunger_change, item_def, pitch) + if user and itemname and pos and hunger_change and item_def then + local name = user:get_player_name() + if mcl_hunger.eat_internal[name] and mcl_hunger.eat_internal[name].do_item_eat then + pitch = 0.95 + end + local def = item_def + -- player height + pos.y = pos.y + 1.5 + local foodtype = minetest.get_item_group(itemname, "food") + if foodtype == 3 then + -- Item is a drink, only play drinking sound (no particle) + minetest.sound_play("survival_thirst_drink", { + max_hear_distance = 12, + gain = 1.0, + pitch = pitch or 1 + math.random(-10, 10)*0.005, + object = user, + }, true) + else + -- Assume the item is a food + -- Add eat particle effect and sound + --local def = minetest.registered_items[itemname] + local texture = def.inventory_image + if not texture or texture == "" then + texture = def.wield_image + end + -- Special item definition field: _food_particles + -- 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() + 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, + gain = 1.0, + pitch = pitch or 1 + math.random(-10, 10)*0.005, + object = user, + }, true) + end + else + return false + end +end + if mcl_hunger.active then -- player-action based hunger changes minetest.register_on_dignode(function(pos, oldnode, player) From cc7a2e0b4142633a55fe727d9a20451478c779e2 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Mon, 15 Jan 2024 06:02:23 +0000 Subject: [PATCH 03/19] Add eating delay entry to changelog.txt --- mods/PLAYER/mcl_hunger/changelog.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/PLAYER/mcl_hunger/changelog.txt b/mods/PLAYER/mcl_hunger/changelog.txt index a56dbcb89..8eb370e94 100644 --- a/mods/PLAYER/mcl_hunger/changelog.txt +++ b/mods/PLAYER/mcl_hunger/changelog.txt @@ -49,3 +49,7 @@ Initial release - Fix mod not working with both intllib and mod security enabled - Add missing screenshot - Rewrite README and use Markdown format + +0.6.0 +----- +- Add eating delay From a78b308a754df793ddfcda5fbb45cd7123f5c75f Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Mon, 15 Jan 2024 06:08:02 +0000 Subject: [PATCH 04/19] Make potions handle delayed eating --- mods/ITEMS/mcl_potions/potions.lua | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 225fffed2..fd9240b92 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -61,7 +61,26 @@ function return_on_use(def, effect, dur) return itemstack end - def.on_use(user, effect, dur) + --def.on_use(user, effect, dur) -- Will do effect immediately but not reduce item count until eating delay ends which makes it exploitable by deliberately not finishing delay + + -- Wrapper for handling mcl_hunger delayed eating + local name = user:get_player_name() + mcl_hunger.eat_internal[name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten + mcl_hunger.eat_internal[name]._custom_var = { + user = user, + effect = effect, + dur = dur, + } + mcl_hunger.eat_internal[name]._custom_func = def.on_use + mcl_hunger.eat_internal[name]._custom_wrapper = function(name) + + mcl_hunger.eat_internal[name]._custom_func( + mcl_hunger.eat_internal[name]._custom_var.user, + mcl_hunger.eat_internal[name]._custom_var.effect, + mcl_hunger.eat_internal[name]._custom_var.dur + ) + end + local old_name, old_count = itemstack:get_name(), itemstack:get_count() itemstack = minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) if old_name ~= itemstack:get_name() or old_count ~= itemstack:get_count() then From b2b2dc4090c1e39d38ea202b6d6bf280122c84a8 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Mon, 15 Jan 2024 06:13:38 +0000 Subject: [PATCH 05/19] Make golden apples handle delayed eating --- mods/ITEMS/mcl_core/craftitems.lua | 62 ++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_core/craftitems.lua b/mods/ITEMS/mcl_core/craftitems.lua index 32a5f7cbc..748c7856f 100644 --- a/mods/ITEMS/mcl_core/craftitems.lua +++ b/mods/ITEMS/mcl_core/craftitems.lua @@ -181,6 +181,56 @@ local function eat_gapple(itemstack, placer, pointed_thing) return gapple_hunger_restore(itemstack, placer, pointed_thing) end +local function eat_gapple_delayed(itemstack, placer, pointed_thing) + + local function eat_gapple(itemstack, placer, pointed_thing) + if pointed_thing.type == "node" then + local node = minetest.get_node(pointed_thing.under) + if placer and not placer: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, placer, itemstack) or itemstack + end + end + elseif pointed_thing.type == "object" then + return itemstack + end + + local regen_duration, absorbtion_factor = 5, 1 + if itemstack:get_name() == "mcl_core:apple_gold_enchanted" then + regen_duration, absorbtion_factor = 20, 4 + mcl_potions.fire_resistance_func(placer, 1, 300) + mcl_potions.leaping_func(placer, 1, 300) + if enable_fapples then + mcl_potions.swiftness_func(placer, absorbtion_factor, 120) + end + end + -- TODO: Absorbtion + mcl_potions.regeneration_func(placer, 2, regen_duration) + --return gapple_hunger_restore(itemstack, placer, pointed_thing) + end + + -- Wrapper for handling mcl_hunger delayed eating + local name = placer:get_player_name() + mcl_hunger.eat_internal[name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten + mcl_hunger.eat_internal[name]._custom_var = { + itemstack = itemstack, + placer = placer, + pointed_thing = pointed_thing, + } + mcl_hunger.eat_internal[name]._custom_func = eat_gapple + mcl_hunger.eat_internal[name]._custom_wrapper = function(name) + + mcl_hunger.eat_internal[name]._custom_func( + mcl_hunger.eat_internal[name]._custom_var.itemstack, + mcl_hunger.eat_internal[name]._custom_var.placer, + mcl_hunger.eat_internal[name]._custom_var.pointed_thing + ) + end + + --mcl_hunger.eat_internal[name]._custom_do_delayed = true -- Only _custom_wrapper will be executed after holding RMB or LMB within a specified delay + minetest.do_item_eat(4, nil, itemstack, placer, pointed_thing) +end + minetest.register_craftitem("mcl_core:apple_gold", { -- TODO: Add special highlight color description = S("Golden Apple"), @@ -188,8 +238,10 @@ minetest.register_craftitem("mcl_core:apple_gold", { wield_image = "mcl_core_apple_golden.png", inventory_image = "mcl_core_apple_golden.png", stack_max = 64, - on_place = eat_gapple, - on_secondary_use = eat_gapple, + --on_place = eat_gapple, -- Will do effect immediately but not reduce item count until eating delay ends which makes it exploitable by deliberately not finishing delay + --on_secondary_use = eat_gapple, + on_place = eat_gapple_delayed, + on_secondary_use = eat_gapple_delayed, groups = { food = 2, eatable = 4, can_eat_when_full = 1 }, _mcl_saturation = 9.6, }) @@ -200,8 +252,10 @@ minetest.register_craftitem("mcl_core:apple_gold_enchanted", { wield_image = "mcl_core_apple_golden.png" .. mcl_enchanting.overlay, inventory_image = "mcl_core_apple_golden.png" .. mcl_enchanting.overlay, stack_max = 64, - on_place = eat_gapple, - on_secondary_use = eat_gapple, + --on_place = eat_gapple, + --on_secondary_use = eat_gapple, + on_place = eat_gapple_delayed, + on_secondary_use = eat_gapple_delayed, groups = { food = 2, eatable = 4, can_eat_when_full = 1 }, _mcl_saturation = 9.6, }) From bee44f41b6e2166b386b0ed797f04107c6a7dc1a Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Mon, 15 Jan 2024 06:18:07 +0000 Subject: [PATCH 06/19] Make milk bucket handle delayed eating --- mods/ITEMS/mcl_mobitems/init.lua | 41 ++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index a47e11bfa..d61dee79a 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -145,6 +145,41 @@ local function drink_milk(itemstack, player, pointed_thing) return bucket end +local function drink_milk_delayed(itemstack, player, pointed_thing) + + local function drink_milk(itemstack, player, pointed_thing) + --local bucket = minetest.do_item_eat(0, "mcl_buckets:bucket_empty", itemstack, player, pointed_thing) + -- Check if we were allowed to drink this (eat delay check) + --if mcl_hunger.active and (bucket:get_name() ~= "mcl_mobitems:milk_bucket" or minetest.is_creative_enabled(player:get_player_name())) then + if mcl_hunger.active and (player:get_inventory():get_stack("main", player:get_wield_index(), itemstack) == "mcl_mobitems:milk_bucket" or minetest.is_creative_enabled(player:get_player_name())) then + mcl_hunger.stop_poison(player) + end + mcl_potions._reset_player_effects(player) + return bucket + end + + -- Wrapper for handling mcl_hunger delayed eating + local name = player:get_player_name() + mcl_hunger.eat_internal[name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten + mcl_hunger.eat_internal[name]._custom_var = { + itemstack = itemstack, + player = player, + pointed_thing = pointed_thing, + } + mcl_hunger.eat_internal[name]._custom_func = drink_milk + mcl_hunger.eat_internal[name]._custom_wrapper = function(name) + + mcl_hunger.eat_internal[name]._custom_func( + mcl_hunger.eat_internal[name]._custom_var.itemstack, + mcl_hunger.eat_internal[name]._custom_var.player, + mcl_hunger.eat_internal[name]._custom_var.pointed_thing + ) + end + + --mcl_hunger.eat_internal[name]._custom_do_delayed = true -- Only _custom_wrapper will be executed after holding RMB or LMB within a specified delay + minetest.do_item_eat(0, "mcl_buckets:bucket_empty", itemstack, player, pointed_thing) +end + minetest.register_craftitem("mcl_mobitems:milk_bucket", { description = S("Milk"), _tt_help = minetest.colorize(mcl_colors.GREEN, S("Removes all status effects")), @@ -152,8 +187,10 @@ minetest.register_craftitem("mcl_mobitems:milk_bucket", { _doc_items_usagehelp = S("Use the placement key to drink the milk."), inventory_image = "mcl_mobitems_bucket_milk.png", wield_image = "mcl_mobitems_bucket_milk.png", - on_place = drink_milk, - on_secondary_use = drink_milk, + --on_place = drink_milk, -- Will do effect immediately but not reduce item count until eating delay ends which makes it exploitable by deliberately not finishing delay + --on_secondary_use = drink_milk, + on_place = drink_milk_delayed, + on_secondary_use = drink_milk_delayed, stack_max = 1, groups = { food = 3, can_eat_when_full = 1 }, }) From 7561e1dc95f3494a5e1e0af8d2f561a5ec716c4d Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Mon, 15 Jan 2024 06:22:31 +0000 Subject: [PATCH 07/19] Make sus stew handle delayed eating --- mods/ITEMS/mcl_sus_stew/init.lua | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_sus_stew/init.lua b/mods/ITEMS/mcl_sus_stew/init.lua index 01c8d2d55..d885dbbd4 100644 --- a/mods/ITEMS/mcl_sus_stew/init.lua +++ b/mods/ITEMS/mcl_sus_stew/init.lua @@ -78,6 +78,29 @@ local function eat_stew(itemstack, user, pointed_thing) end end +local function eat_stew_delayed(itemstack, user, pointed_thing) + -- Wrapper for handling mcl_hunger delayed eating + local name = user:get_player_name() + mcl_hunger.eat_internal[name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten + mcl_hunger.eat_internal[name]._custom_var = { + itemstack = itemstack, + user = user, + pointed_thing = pointed_thing, + } + mcl_hunger.eat_internal[name]._custom_func = eat_stew + mcl_hunger.eat_internal[name]._custom_wrapper = function(name) + + mcl_hunger.eat_internal[name]._custom_func( + mcl_hunger.eat_internal[name]._custom_var.itemstack, + mcl_hunger.eat_internal[name]._custom_var.user, + mcl_hunger.eat_internal[name]._custom_var.pointed_thing + ) + end + + mcl_hunger.eat_internal[name]._custom_do_delayed = true -- Only _custom_wrapper will be executed after holding RMB or LMB within a specified delay + --minetest.do_item_eat(0, "mcl_core:bowl", itemstack, user, pointed_thing) +end + minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) if itemstack:get_name() ~= "mcl_sus_stew:stew" then return end for f,e in pairs(flower_effect) do @@ -96,8 +119,10 @@ minetest.register_craftitem("mcl_sus_stew:stew",{ description = S("Suspicious Stew"), inventory_image = "sus_stew.png", stack_max = 1, - on_place = eat_stew, - on_secondary_use = eat_stew, + --on_place = eat_stew, + --on_secondary_use = eat_stew, + on_place = eat_stew_delayed, + on_secondary_use = eat_stew_delayed, groups = { food = 2, eatable = 4, can_eat_when_full = 1, not_in_creative_inventory=1,}, _mcl_saturation = 7.2, }) From 184f1575eeb8ba0410fab6c5cb402f6971d822c1 Mon Sep 17 00:00:00 2001 From: James David Clarke Date: Mon, 15 Jan 2024 08:04:08 +0000 Subject: [PATCH 08/19] Added mcl_eating_delay setting in settingtypes.txt --- settingtypes.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/settingtypes.txt b/settingtypes.txt index b10666deb..ac3399498 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -105,6 +105,10 @@ mcl_hunger_debug (Hunger debug) bool false # Default: 0.5 s mcl_health_regen_delay (Health regen delay) float 0.5 0 +# Eating delay while holding right-click +# Default: 1.61 s +mcl_eating_delay (Eating delay) float 1.61 0 + [Mobs] # If enabled, mobs will spawn naturally. This does not affect # affect mob spawners. From 109aed75df52947e8986f96f6c3275930eb99707 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Tue, 16 Jan 2024 06:58:10 +0000 Subject: [PATCH 09/19] Fix sus stew not having eating particle & sound effects and eating slow speed getting stuck on login --- mods/PLAYER/mcl_hunger/init.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mods/PLAYER/mcl_hunger/init.lua b/mods/PLAYER/mcl_hunger/init.lua index ddc771e4a..c492b8e63 100644 --- a/mods/PLAYER/mcl_hunger/init.lua +++ b/mods/PLAYER/mcl_hunger/init.lua @@ -67,6 +67,7 @@ minetest.register_on_joinplayer(function(player) _custom_wrapper = nil, -- Will execute alongside minetest.do_item_eat if not empty and _custom_itemstack is equal to current player itemstack _custom_do_delayed = false, -- If true, then will execute only _custom_wrapper after holding RMB or LMB within a delay specified by mcl_hunger.EATING_DELAY (Use to bypass minetest.do_item_eat entirely) } + playerphysics.remove_physics_factor(player, "speed", "mcl_hunger:eating_speed") end) -- Clear when player leaves @@ -284,6 +285,18 @@ minetest.register_globalstep(function(dtime) if eat_effects_cooldown[player] > 0.2 then eat_effects_cooldown[player] = 0 + if not mcl_hunger.eat_internal[player_name].user then + mcl_hunger.eat_internal[player_name].user = player + end + + if not mcl_hunger.eat_internal[player_name].itemname then + mcl_hunger.eat_internal[player_name].itemname = current_itemstack:get_name() + end + + if not mcl_hunger.eat_internal[player_name].hp_change then + mcl_hunger.eat_internal[player_name].hp_change = 0 + end + local pos = player:get_pos() local itemname = mcl_hunger.eat_internal[player_name].itemname local def = minetest.registered_items[itemname] From 4dd04b4c91ac08da7778ed2d6d3556cd3efd4317 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Tue, 16 Jan 2024 09:08:45 +0000 Subject: [PATCH 10/19] Fix sus stew not leaving bowl after use --- mods/ITEMS/mcl_sus_stew/init.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mods/ITEMS/mcl_sus_stew/init.lua b/mods/ITEMS/mcl_sus_stew/init.lua index d885dbbd4..02565757c 100644 --- a/mods/ITEMS/mcl_sus_stew/init.lua +++ b/mods/ITEMS/mcl_sus_stew/init.lua @@ -95,6 +95,12 @@ local function eat_stew_delayed(itemstack, user, pointed_thing) mcl_hunger.eat_internal[name]._custom_var.user, mcl_hunger.eat_internal[name]._custom_var.pointed_thing ) + + local user = mcl_hunger.eat_internal[name]._custom_var.user + + minetest.after(0, function() + user:get_inventory():set_stack("main", user:get_wield_index(), "mcl_core:bowl") + end) end mcl_hunger.eat_internal[name]._custom_do_delayed = true -- Only _custom_wrapper will be executed after holding RMB or LMB within a specified delay From 11d0062255c37554f06683f19e889f4075418932 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Tue, 16 Jan 2024 12:25:34 +0000 Subject: [PATCH 11/19] Change mushroom stew food group to not be categorized as a drink and be eaten with particles --- mods/ITEMS/mcl_mushrooms/small.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_mushrooms/small.lua b/mods/ITEMS/mcl_mushrooms/small.lua index f6fbd2909..4d1ffa2f5 100644 --- a/mods/ITEMS/mcl_mushrooms/small.lua +++ b/mods/ITEMS/mcl_mushrooms/small.lua @@ -87,7 +87,7 @@ minetest.register_craftitem("mcl_mushrooms:mushroom_stew", { inventory_image = "farming_mushroom_stew.png", on_place = minetest.item_eat(6, "mcl_core:bowl"), on_secondary_use = minetest.item_eat(6, "mcl_core:bowl"), - groups = { food = 3, eatable = 6 }, + groups = { food = 2, eatable = 6 }, _mcl_saturation = 7.2, stack_max = 1, }) From 7b42779fe2e0320813899e6b68ab8d3fc725cdbc Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Tue, 16 Jan 2024 12:28:24 +0000 Subject: [PATCH 12/19] Change rabbit stew food group to not be categorized as a drink and be eaten with particles --- mods/ITEMS/mcl_mobitems/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index d61dee79a..c27ad4e10 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -335,7 +335,7 @@ minetest.register_craftitem("mcl_mobitems:rabbit_stew", { stack_max = 1, on_place = minetest.item_eat(10, "mcl_core:bowl"), on_secondary_use = minetest.item_eat(10, "mcl_core:bowl"), - groups = { food = 3, eatable = 10 }, + groups = { food = 2, eatable = 10 }, _mcl_saturation = 12.0, }) From be711ea727b3a07b032390f0c678bdf6bb5e90a7 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Tue, 16 Jan 2024 12:31:59 +0000 Subject: [PATCH 13/19] Change beetroot soup food group to not be categorized as a drink and be eaten with particles --- mods/ITEMS/mcl_farming/beetroot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_farming/beetroot.lua b/mods/ITEMS/mcl_farming/beetroot.lua index 3785db111..f32b2bf8e 100644 --- a/mods/ITEMS/mcl_farming/beetroot.lua +++ b/mods/ITEMS/mcl_farming/beetroot.lua @@ -157,7 +157,7 @@ minetest.register_craftitem("mcl_farming:beetroot_soup", { wield_image = "mcl_farming_beetroot_soup.png", on_place = minetest.item_eat(6, "mcl_core:bowl"), on_secondary_use = minetest.item_eat(6, "mcl_core:bowl"), - groups = { food = 3, eatable = 6 }, + groups = { food = 2, eatable = 6 }, _mcl_saturation = 7.2, }) From 93dff87a5eecf1ea7cfa13f99ef86096925d090c Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Thu, 18 Jan 2024 14:15:43 +0000 Subject: [PATCH 14/19] Add mcl_hunger.is_eating(name) API --- mods/PLAYER/mcl_hunger/init.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/mods/PLAYER/mcl_hunger/init.lua b/mods/PLAYER/mcl_hunger/init.lua index c492b8e63..61b6b72f2 100644 --- a/mods/PLAYER/mcl_hunger/init.lua +++ b/mods/PLAYER/mcl_hunger/init.lua @@ -43,6 +43,18 @@ mcl_hunger.debug = false -- Cooldown timers for each player, to force a short delay between consuming 2 food items mcl_hunger.last_eat = {} +-- Is player eating API +function mcl_hunger.is_eating(name) + local result + if name then + if type(name) ~= "string" then + name = name:get_player_name() + end + result = mcl_hunger.eat_internal[name].is_eating_no_padding + end + return result +end + -- Variables for each player, to handle delayed eating mcl_hunger.eat_internal = {} @@ -52,6 +64,7 @@ minetest.register_on_joinplayer(function(player) mcl_hunger.eat_internal[name] = { is_eating = false, + is_eating_no_padding = false, itemname = nil, item_definition = nil, hp_change = nil, @@ -184,6 +197,7 @@ local function clear_eat_internal_and_timers(player, player_name) playerphysics.remove_physics_factor(player, "speed", "mcl_hunger:eating_speed") mcl_hunger.eat_internal[player_name] = { is_eating = false, + is_eating_no_padding = false, itemname = nil, item_definition = nil, hp_change = nil, @@ -253,6 +267,9 @@ minetest.register_globalstep(function(dtime) -- Eating delay code if mcl_hunger.eat_internal[player_name].is_eating or mcl_hunger.eat_internal[player_name]._custom_do_delayed then + mcl_hunger.eat_internal[player_name].is_eating = true + mcl_hunger.eat_internal[player_name].is_eating_no_padding = true + local control = player:get_player_control() local inv = player:get_inventory() local current_itemstack = player:get_wielded_item() @@ -340,6 +357,7 @@ minetest.register_globalstep(function(dtime) elseif eat_start_timers[player] and eat_start_timers[player] > 0.2 then playerphysics.remove_physics_factor(player, "speed", "mcl_hunger:eating_speed") + mcl_hunger.eat_internal[player_name].is_eating_no_padding = false elseif eat_start_timers[player] and eat_start_timers[player] > mcl_hunger.EATING_TOUCHSCREEN_DELAY_PADDING then clear_eat_internal_and_timers(player, player_name) From b56424a0b6fed0d42c6bb5d238139ff2054e3047 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Thu, 18 Jan 2024 14:18:48 +0000 Subject: [PATCH 15/19] Integrate mcl_hunger.is_eating(name) API into item eat code --- mods/PLAYER/mcl_hunger/hunger.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index 623d459f9..fec24eafe 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -41,6 +41,7 @@ function minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, poi if not no_eat_delay and not mcl_hunger.eat_internal[name].is_eating and not mcl_hunger.eat_internal[name].do_item_eat and (can_eat_when_full or (mcl_hunger.get_hunger(user) < 20)) then local itemname = itemstack:get_name() mcl_hunger.eat_internal[name].is_eating = true + mcl_hunger.eat_internal[name].is_eating_no_padding = true mcl_hunger.eat_internal[name].itemname = itemname mcl_hunger.eat_internal[name].item_definition = minetest.registered_items[itemname] mcl_hunger.eat_internal[name].hp_change = hp_change From 86c10002a6569553c87385887d533e92f8847218 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Sun, 21 Jan 2024 08:38:20 +0000 Subject: [PATCH 16/19] Fix golden apple item frame duplication bug --- mods/ITEMS/mcl_core/craftitems.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mods/ITEMS/mcl_core/craftitems.lua b/mods/ITEMS/mcl_core/craftitems.lua index 748c7856f..e89fe124a 100644 --- a/mods/ITEMS/mcl_core/craftitems.lua +++ b/mods/ITEMS/mcl_core/craftitems.lua @@ -183,6 +183,17 @@ end local function eat_gapple_delayed(itemstack, placer, pointed_thing) + if pointed_thing.type == "node" then + local node = minetest.get_node(pointed_thing.under) + if placer and not placer: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, placer, itemstack) or itemstack + end + end + elseif pointed_thing.type == "object" then + return itemstack + end + local function eat_gapple(itemstack, placer, pointed_thing) if pointed_thing.type == "node" then local node = minetest.get_node(pointed_thing.under) From 473c85c54378d2594f992e751c6d6f7af00d8487 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Sun, 21 Jan 2024 08:40:42 +0000 Subject: [PATCH 17/19] Fix bucket milk item frame duplication bug --- mods/ITEMS/mcl_mobitems/init.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index c27ad4e10..421ee184e 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -147,6 +147,17 @@ end local function drink_milk_delayed(itemstack, player, pointed_thing) + if pointed_thing.type == "node" then + 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 + elseif pointed_thing.type == "object" then + return itemstack + end + local function drink_milk(itemstack, player, pointed_thing) --local bucket = minetest.do_item_eat(0, "mcl_buckets:bucket_empty", itemstack, player, pointed_thing) -- Check if we were allowed to drink this (eat delay check) From c0a5c63601593df0c9f4449d3845d82f2d745511 Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Sun, 21 Jan 2024 08:43:02 +0000 Subject: [PATCH 18/19] Fix sus stew item frame duplication bug --- mods/ITEMS/mcl_sus_stew/init.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mods/ITEMS/mcl_sus_stew/init.lua b/mods/ITEMS/mcl_sus_stew/init.lua index 02565757c..d34dbbf00 100644 --- a/mods/ITEMS/mcl_sus_stew/init.lua +++ b/mods/ITEMS/mcl_sus_stew/init.lua @@ -79,6 +79,21 @@ local function eat_stew(itemstack, user, pointed_thing) end local function eat_stew_delayed(itemstack, user, pointed_thing) + + if pointed_thing.type == "node" then + if user and not user:get_player_control().sneak then + -- Use pointed node's on_rightclick function first, if present + local node = minetest.get_node(pointed_thing.under) + if user and not user: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, user, itemstack) or itemstack + end + end + end + elseif pointed_thing.type == "object" then + return itemstack + end + -- Wrapper for handling mcl_hunger delayed eating local name = user:get_player_name() mcl_hunger.eat_internal[name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten From 5154dce8d0b585ec96b8c209117c032fb1615d7a Mon Sep 17 00:00:00 2001 From: Eliy21 Date: Sun, 21 Jan 2024 08:46:48 +0000 Subject: [PATCH 19/19] Use table.update() on mcl_hunger.eat_internal[name] in the item eat code --- mods/PLAYER/mcl_hunger/hunger.lua | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index fec24eafe..de6369359 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -40,15 +40,17 @@ function minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, poi -- Don't allow eating when player has full hunger bar (some exceptional items apply) if not no_eat_delay and not mcl_hunger.eat_internal[name].is_eating and not mcl_hunger.eat_internal[name].do_item_eat and (can_eat_when_full or (mcl_hunger.get_hunger(user) < 20)) then local itemname = itemstack:get_name() - mcl_hunger.eat_internal[name].is_eating = true - mcl_hunger.eat_internal[name].is_eating_no_padding = true - mcl_hunger.eat_internal[name].itemname = itemname - mcl_hunger.eat_internal[name].item_definition = minetest.registered_items[itemname] - mcl_hunger.eat_internal[name].hp_change = hp_change - mcl_hunger.eat_internal[name].replace_with_item = replace_with_item - mcl_hunger.eat_internal[name].itemstack = itemstack - mcl_hunger.eat_internal[name].user = user - mcl_hunger.eat_internal[name].pointed_thing = pointed_thing + table.update(mcl_hunger.eat_internal[name], { + is_eating = true, + is_eating_no_padding = true, + itemname = itemname, + item_definition = minetest.registered_items[itemname], + hp_change = hp_change, + replace_with_item = replace_with_item, + itemstack = itemstack, + user = user, + pointed_thing = pointed_thing + }) elseif (mcl_hunger.eat_internal[name].do_item_eat or no_eat_delay) and (can_eat_when_full or (mcl_hunger.get_hunger(user) < 20)) then if mcl_hunger.eat_internal[name]._custom_itemstack and mcl_hunger.eat_internal[name]._custom_wrapper and