diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index 107e60705..0e76b0d8f 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -12,18 +12,30 @@ core.do_item_eat = function(hp_change, replace_with_item, itemstack, user, point end local old_itemstack = itemstack - itemstack = mcl_hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing) - for _, callback in pairs(core.registered_on_item_eats) do - local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack) - if result then - return result + + local name = user:get_player_name() + + -- Allow eating only after a delay of 2 seconds. + -- This prevents eating as an excessive speed. + -- Yes, os.time() is not a precise timer but it is good enough for our purposes. + -- FIXME: In singleplayer, there's a cheat to circumvent this, simply by pausing the game between eats. + -- This is because os.time() obviously does not care about the pause. A fix needs a different timer mechanism. + if (mcl_hunger.last_eat[name] < 0) or (os.difftime(os.time(), mcl_hunger.last_eat[name]) >= 2) then + itemstack = mcl_hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing) + for _, callback in pairs(core.registered_on_item_eats) do + local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack) + if result then + return result + end end + mcl_hunger.last_eat[name] = os.time() end + return itemstack end -- food functions -local food = mcl_hunger.food +local food = {} function mcl_hunger.register_food(name, hunger_change, replace_with_item, poisontime, poison, exhaust, poisonchance, sound) food[name] = {} @@ -87,7 +99,7 @@ local function poisonp(tick, time, time_left, damage, exhaustion, player) player:set_hp(player:get_hp()-damage) end mcl_hunger.exhaust(player:get_player_name(), exhaustion) - + end -- Immediately stop all poisonings for this player @@ -101,6 +113,7 @@ local poisonrandomizer = PseudoRandom(os.time()) function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poison, exhaust, poisonchance, sound) return function(itemstack, user, pointed_thing) local itemname = itemstack:get_name() + if itemstack:take_item() ~= nil and user ~= nil then local name = user:get_player_name() local hp = user:get_hp() diff --git a/mods/PLAYER/mcl_hunger/init.lua b/mods/PLAYER/mcl_hunger/init.lua index a6751ed71..f9a3070b0 100644 --- a/mods/PLAYER/mcl_hunger/init.lua +++ b/mods/PLAYER/mcl_hunger/init.lua @@ -28,7 +28,6 @@ mcl_hunger.active = false if minetest.setting_getbool("enable_damage") then mcl_hunger.active = true -mcl_hunger.food = {} -- Debug Mode. If enabled, saturation and exhaustion are shown as well. -- NOTE: Read-only. The setting should only be read at the beginning, this mod is not @@ -51,6 +50,9 @@ end -- Count number of poisonings a player has at once mcl_hunger.poisonings = {} +-- Cooldown timers for each player, to force a short delay between consuming 2 food items +mcl_hunger.last_eat = {} + -- HUD item ids local hunger_hud = {} @@ -175,12 +177,15 @@ minetest.register_on_joinplayer(function(player) local inv = player:get_inventory() inv:set_size("hunger", 3) mcl_hunger.poisonings[name] = 0 + mcl_hunger.last_eat[name] = -1 init_hud(player) end) minetest.register_on_respawnplayer(function(player) -- reset hunger (and save) local name = player:get_player_name() + mcl_hunger.last_eat[name] = -1 + local h, s, e = 20, mcl_hunger.SATURATION_INIT, 0 mcl_hunger.set_hunger(player, h, false) mcl_hunger.set_saturation(player, s, false)