1 local minetest = minetest
2 local mod_storage = minetest.get_mod_storage()
3 local player_hunger_data = {} -- array to hold hunger data
4 local hunger_class = {}
5 hunger_pointer = {} -- allow other mods to access local data
8 -- creates volitile data for the game to use
9 hunger_class.set_data = function(player,data)
10 local name = player:get_player_name()
11 if not player_hunger_data[name] then
12 player_hunger_data[name] = {}
15 for index,i_data in pairs(data) do
16 player_hunger_data[name][index] = i_data
20 hud_manager.change_hud({
29 -- indexes hunger data and returns it
30 hunger_class.get_data = function(player,requested_data)
31 local name = player:get_player_name()
32 if player_hunger_data[name] then
35 for index,i_data in pairs(requested_data) do
36 if player_hunger_data[name][i_data] then
37 data_list[i_data] = player_hunger_data[name][i_data]
50 -- removes hunger data
51 hunger_class.terminate = function(player)
52 local name = player:get_player_name()
53 if player_hunger_data[name] then
54 player_hunger_data[name] = nil
58 -- loads data from mod storage
59 hunger_class.load_data = function(player)
60 local name = player:get_player_name()
61 if mod_storage:get_int(name.."h_save") > 0 then
63 hunger = mod_storage:get_int(name.."hunger" ),
64 satiation = mod_storage:get_int(name.."satiation" ),
65 exhaustion = mod_storage:get_int(name.."exhaustion" ),
66 regeneration_interval = mod_storage:get_int(name.."regeneration_interval")
72 regeneration_interval = 0,
78 -- saves data to be utilized on next login
79 hunger_class.save_data = function(player)
81 if type(player) ~= "string" and player:is_player() then
82 name = player:get_player_name()
83 elseif type(player) == "string" then
86 if player_hunger_data[name] then
87 for index,integer in pairs(player_hunger_data[name]) do
88 mod_storage:set_int(name..index,integer)
92 mod_storage:set_int(name.."h_save", 1)
94 player_hunger_data[name] = nil
97 -- is used for shutdowns to save all data
98 hunger_class.save_all = function()
99 for name,data in pairs(player_hunger_data) do
100 hunger_class.save_data(name)
104 -- an easy translation pool
105 hunger_class.satiation_pool = {
112 -- ticks up the exhaustion when counting down satiation
113 hunger_class.tick_up_satiation = function(m_data,exhaustion)
114 return(exhaustion + hunger_class.satiation_pool[m_data])
117 -- an easy translation pool
118 hunger_class.hunger_pool = {
125 -- ticks up the exhaustion when counting down hunger
126 hunger_class.tick_up_hunger = function(m_data,exhaustion)
127 return(exhaustion + hunger_class.hunger_pool[m_data])
130 -- allows other mods to set hunger data
131 hunger_pointer.set_data = function(player,data)
132 local name = player:get_player_name()
133 if not player_hunger_data[name] then
134 player_hunger_data[name] = {}
137 for index,i_data in pairs(data) do
138 player_hunger_data[name][index] = i_data
142 hud_manager.change_hud({
151 -- allows other mods to index hunger data
152 hunger_pointer.get_data = function(player,requested_data)
153 local name = player:get_player_name()
154 if player_hunger_data[name] then
157 for index,i_data in pairs(requested_data) do
158 if player_hunger_data[name][i_data] then
159 data_list[i_data] = player_hunger_data[name][i_data]
172 -- saves specific users data for when they relog
173 minetest.register_on_leaveplayer(function(player)
174 hunger_class.save_data(player)
175 hunger_class.terminate(player)
178 -- save all data to mod storage on shutdown
179 minetest.register_on_shutdown(function()
180 hunger_class.save_all()
183 -- create new data for hunger per player
184 minetest.register_on_joinplayer(function(player)
185 local name = player:get_player_name()
186 local data = hunger_class.load_data(player)
188 hunger_class.set_data(player,data)
190 hud_manager.add_hud(player,"hunger_bg",{
191 hud_elem_type = "statbar",
192 position = {x = 0.5, y = 1},
193 text = "hunger_icon_bg.png",
196 size = {x = 24, y = 24},
197 offset = {x = 24*10, y= -(48 + 24 + 39)},
199 hud_manager.add_hud(player,"hunger",{
200 hud_elem_type = "statbar",
201 position = {x = 0.5, y = 1},
202 text = "hunger_icon.png",
203 number = data.hunger,
205 size = {x = 24, y = 24},
206 offset = {x = 24*10, y= -(48 + 24 + 39)},
210 -- resets the players hunger settings to max
211 minetest.register_on_respawnplayer(function(player)
212 hunger_class.set_data(player,{
215 regeneration_interval = 0,
222 --this is the max exhaustion a player will get before their
223 --satiation goes down and rolls over
224 local exhaustion_peak = 384
225 --when satiation runs out this is when the hunger peak variable
226 --is used, everytime the player rolls over this their hunger ticks down
227 --based on what they're doing
228 local hunger_peak = 64
231 local function hunger_update()
232 for _,player in ipairs(minetest.get_connected_players()) do
233 --do not regen player's health if dead - this will be reused for 1up apples
234 if player:get_hp() > 0 then
236 local data = hunger_class.get_data(player,{
237 "hunger","satiation","exhaustion","regeneration_interval"
241 local m_data = movement_pointer.get_data(player,{"state"})
243 m_data = m_data.state
246 --we must seperate these two values
248 local input = player:get_player_control()
249 if input.jump or input.right or input.left or input.down or input.up then
254 -- count up the exhaustion of the player moving around
256 -- count down invisible satiation bar
257 if data.satiation > 0 and data.hunger >= 20 then
258 data.exhaustion = hunger_class.tick_up_satiation(m_data,data.exhaustion)
259 if data.exhaustion >= exhaustion_peak then
260 data.satiation = data.satiation - 1
261 data.exhaustion = data.exhaustion - exhaustion_peak
263 --reset this to use for the hunger tick
264 if data.satiation == 0 then
267 hunger_class.set_data(player,{satiation=data.satiation})
269 hunger_class.set_data(player,{exhaustion=data.exhaustion})
270 -- count down hunger bars
271 elseif data.hunger > 0 then
272 data.exhaustion = hunger_class.tick_up_hunger(m_data,data.exhaustion)
274 if data.exhaustion >= hunger_peak then
275 --don't allow hunger to go negative
276 if data.hunger > 0 then
278 data.hunger = data.hunger - 1
279 hunger_class.set_data(player,{hunger=data.hunger})
282 hunger_class.set_data(player,{exhaustion=data.exhaustion})
283 -- hurt the player if hunger bar empty
284 elseif data.hunger <= 0 then
285 data.exhaustion = data.exhaustion + 1
286 local hp = player:get_hp()
287 if hp > 0 and data.exhaustion >= 2 then
291 hunger_class.set_data(player,{exhaustion=data.exhaustion})
295 local hp = player:get_hp()
296 local drowning = drowning_pointer.get_data(player,{"drowning"})
298 drowning = drowning.drowning
300 --make regeneration happen every second
301 if drowning == 0 and data.hunger >= 20 and hp < 20 then -- meta:get_int("on_fire") == 0
302 --print(regeneration_interval,"--------------------------")
303 data.regeneration_interval = data.regeneration_interval + 1
304 if data.regeneration_interval >= 2 then
306 data.exhaustion = data.exhaustion + 32
307 data.regeneration_interval = 0
309 hunger_class.set_data(player,{
310 regeneration_interval = data.regeneration_interval,
311 exhaustion = data.exhaustion ,
312 satiation = data.satiation ,
315 hunger_class.set_data(player,{regeneration_interval=data.regeneration_interval})
317 --reset the regen interval
319 hunger_class.set_data(player,{regeneration_interval=0})
324 minetest.after(0.5, function()
329 minetest.register_on_mods_loaded(function()
330 minetest.after(0,function()
335 --take away hunger and satiation randomly while mining
336 minetest.register_on_dignode(function(pos, oldnode, digger)
337 if digger and digger:is_player() then
338 local data = hunger_class.get_data(digger,{"exhaustion"})
339 data.exhaustion = data.exhaustion + math.random(0,2)
340 hunger_class.set_data(digger,{exhaustion=data.exhaustion})
344 --allow players to eat food
345 function minetest.eat_food(player,item)
346 local meta = player:get_meta()
348 local player_hunger = meta:get_int("hunger")
349 local player_satiation = meta:get_int("satiation")
352 if type(item) == "string" then
353 item = ItemStack(item)
354 elseif type(item) == "table" then
355 item = ItemStack(item.name)
358 item = item:get_name()
360 local satiation = minetest.get_item_group(item, "satiation")
361 local hunger = minetest.get_item_group(item, "hunger")
363 if player_hunger < 20 then
364 player_hunger = player_hunger + hunger
365 if player_hunger > 20 then
369 if player_satiation < satiation then
370 player_satiation = satiation
373 meta:set_int("exhaustion", 0)
374 meta:set_int("hunger", player_hunger)
375 meta:set_int("satiation", player_satiation)
376 local hunger_bar = meta:get_int("hunger_bar")
377 player:hud_change(hunger_bar, "number", player_hunger)
378 local stack = player:get_wielded_item()
380 player:set_wielded_item(stack)
383 function minetest.register_food(name,def)
384 minetest.register_craftitem(":"..name, {
385 description = def.description,
386 inventory_image = def.texture,
387 groups = {satiation=def.satiation,hunger=def.hunger},
390 minetest.register_node(":"..name.."node", {
391 tiles = {def.texture},
392 drawtype = "allfaces",
397 minetest.register_chatcommand("hungry", {
399 description = "A debug command to test food",
400 privs = {server = true},
401 func = function(name)
402 local player = minetest.get_player_by_name(name)
403 hunger_class.set_data(player,{