1 local minetest,math,ItemStack =
2 minetest,math,ItemStack
3 local mod_storage = minetest.get_mod_storage()
4 local player_hunger_data = {} -- array to hold hunger data
5 local hunger_class = {}
6 hunger_pointer = {} -- allow other mods to access local data
7 hunger_class.data = nil
8 hunger_class.drowning = nil
10 hunger_class.name = nil
11 hunger_class.i_data = nil
12 hunger_class.count = nil
13 hunger_class.food_data = {}
14 hunger_class.pairs = pairs
15 hunger_class.ipairs = ipairs
16 hunger_class.get_connected = minetest.get_connected_players
17 hunger_class.get_group = minetest.get_item_group
19 --this is the max exhaustion a player will get before their
20 --satiation goes down and rolls over
21 hunger_class.exhaustion_peak = 512
22 --when satiation runs out this is when the hunger peak variable
23 --is used, everytime the player rolls over this their hunger ticks down
24 --based on what they're doing
25 hunger_class.hunger_peak = 128
27 -- creates volitile data for the game to use
28 hunger_class.set_data = function(player,data)
29 hunger_class.name = player:get_player_name()
30 if not player_hunger_data[hunger_class.name] then
31 player_hunger_data[hunger_class.name] = {}
34 for index,i_data in hunger_class.pairs(data) do
35 player_hunger_data[hunger_class.name][index] = i_data
39 hud_manager.change_hud({
49 hunger_class.get_data = function(player,requested_data)
50 hunger_class.name = player:get_player_name()
51 if player_hunger_data[hunger_class.name] then
52 hunger_class.i_data = {}
53 hunger_class.count = 0
54 for _,i_data in hunger_class.pairs(requested_data) do
55 if player_hunger_data[hunger_class.name][i_data] then
56 hunger_class.i_data[i_data] = player_hunger_data[hunger_class.name][i_data]
57 hunger_class.count = hunger_class.count + 1
61 if hunger_class.count > 0 then
62 return(hunger_class.i_data)
70 -- removes hunger data
71 hunger_class.terminate = function(player)
72 hunger_class.name = player:get_player_name()
73 if player_hunger_data[hunger_class.name] then
74 player_hunger_data[hunger_class.name] = nil
78 -- loads data from mod storage
79 hunger_class.load_data = function(player)
80 hunger_class.name = player:get_player_name()
81 if mod_storage:get_int(hunger_class.name.."h_save") > 0 then
83 hunger = mod_storage:get_int(hunger_class.name.."hunger" ),
84 satiation = mod_storage:get_int(hunger_class.name.."satiation" ),
85 exhaustion = mod_storage:get_int(hunger_class.name.."exhaustion" ),
86 regeneration_interval = mod_storage:get_int(hunger_class.name.."regeneration_interval")
92 regeneration_interval = 0,
98 -- saves data to be utilized on next login
99 hunger_class.save_data = function(player)
100 if type(player) ~= "string" and player:is_player() then
101 hunger_class.name = player:get_player_name()
102 elseif type(player) == "string" then
103 hunger_class.name = player
105 if player_hunger_data[hunger_class.name] then
106 for index,integer in hunger_class.pairs(player_hunger_data[hunger_class.name]) do
107 mod_storage:set_int(hunger_class.name..index,integer)
111 mod_storage:set_int(hunger_class.name.."h_save", 1)
113 player_hunger_data[hunger_class.name] = nil
116 -- is used for shutdowns to save all data
117 hunger_class.save_all = function()
118 for name,data in hunger_class.pairs(player_hunger_data) do
119 hunger_class.save_data(name)
123 -- an easy translation pool
124 hunger_class.satiation_pool = {
131 -- ticks up the exhaustion when counting down satiation
132 hunger_class.tick_up_satiation = function(m_data,exhaustion)
133 return(exhaustion + hunger_class.satiation_pool[m_data])
136 -- an easy translation pool
137 hunger_class.hunger_pool = {
144 -- ticks up the exhaustion when counting down hunger
145 hunger_class.tick_up_hunger = function(m_data,exhaustion)
146 return(exhaustion + hunger_class.hunger_pool[m_data])
149 -- allows other mods to set hunger data
150 hunger_pointer.set_data = function(player,data)
151 hunger_class.name = player:get_player_name()
152 if not player_hunger_data[hunger_class.name] then
153 player_hunger_data[hunger_class.name] = {}
156 for index,i_data in hunger_class.pairs(data) do
157 player_hunger_data[hunger_class.name][index] = i_data
161 hud_manager.change_hud({
170 -- allows other mods to index hunger data
171 hunger_pointer.get_data = function(player,requested_data)
172 hunger_class.name = player:get_player_name()
173 if player_hunger_data[hunger_class.name] then
174 hunger_class.i_data = {}
175 hunger_class.count = 0
176 for _,i_data in hunger_class.pairs(requested_data) do
177 if player_hunger_data[hunger_class.name][i_data] then
178 hunger_class.i_data[i_data] = player_hunger_data[hunger_class.name][i_data]
179 hunger_class.count = hunger_class.count + 1
182 if hunger_class.count > 0 then
183 return(hunger_class.i_data)
191 -- saves specific users data for when they relog
192 minetest.register_on_leaveplayer(function(player)
193 hunger_class.save_data(player)
194 hunger_class.terminate(player)
197 -- save all data to mod storage on shutdown
198 minetest.register_on_shutdown(function()
199 hunger_class.save_all()
202 -- create new data for hunger per player
203 minetest.register_on_joinplayer(function(player)
204 hunger_class.name = player:get_player_name()
205 hunger_class.data = hunger_class.load_data(player)
207 hunger_class.set_data(player,hunger_class.data)
209 hud_manager.add_hud(player,"hunger_bg",{
210 hud_elem_type = "statbar",
211 position = {x = 0.5, y = 1},
212 text = "hunger_icon_bg.png",
215 size = {x = 24, y = 24},
216 offset = {x = 24*10, y= -(48 + 24 + 39)},
218 hud_manager.add_hud(player,"hunger",{
219 hud_elem_type = "statbar",
220 position = {x = 0.5, y = 1},
221 text = "hunger_icon.png",
222 number = hunger_class.data.hunger,
224 size = {x = 24, y = 24},
225 offset = {x = 24*10, y= -(48 + 24 + 39)},
229 -- resets the players hunger settings to max
230 minetest.register_on_respawnplayer(function(player)
231 hunger_class.set_data(player,{
234 regeneration_interval = 0,
240 local function hunger_update()
241 for _,player in hunger_class.ipairs(hunger_class.get_connected()) do
242 --do not regen player's health if dead - this will be reused for 1up apples
243 if player:get_hp() > 0 then
246 hunger_class.data = hunger_class.get_data(player,{
247 "hunger","satiation","exhaustion","regeneration_interval"
250 print(dump(hunger_class.data))
253 local m_data = movement_pointer.get_data(player,{"state"})
255 m_data = m_data.state
258 -- if player is moving in state 0 add 0.5
260 local input = player:get_player_control()
261 if input.jump or input.right or input.left or input.down or input.up then
268 -- count down invisible satiation bar
269 if hunger_class.data.satiation > 0 and hunger_class.data.hunger >= 20 then
270 hunger_class.data.exhaustion = hunger_class.tick_up_satiation(m_data, hunger_class.data.exhaustion)
271 if hunger_class.data.exhaustion >= hunger_class.exhaustion_peak then
273 hunger_class.data.satiation = hunger_class.data.satiation - 1
274 hunger_class.data.exhaustion = hunger_class.data.exhaustion - hunger_class.exhaustion_peak
276 --reset this to use for the hunger tick
277 if hunger_class.data.satiation == 0 then
278 hunger_class.data.exhaustion = 0
281 hunger_class.set_data(player,{satiation=hunger_class.data.satiation})
283 hunger_class.set_data(player,{exhaustion=hunger_class.data.exhaustion})
284 -- count down hunger bars
285 elseif hunger_class.data.hunger > 0 then
286 hunger_class.data.exhaustion = hunger_class.tick_up_hunger(m_data,hunger_class.data.exhaustion)
288 if hunger_class.data.exhaustion >= hunger_class.hunger_peak then
289 --don't allow hunger to go negative
290 if hunger_class.data.hunger > 0 then
291 hunger_class.data.exhaustion = hunger_class.data.exhaustion - hunger_class.hunger_peak
292 hunger_class.data.hunger = hunger_class.data.hunger - 1
293 hunger_class.set_data(player,{hunger=hunger_class.data.hunger})
296 hunger_class.set_data(player,{exhaustion=hunger_class.data.exhaustion})
297 -- hurt the player if hunger bar empty
298 elseif hunger_class.data.hunger <= 0 then
299 hunger_class.data.exhaustion = hunger_class.data.exhaustion + 1
300 local hp = player:get_hp()
301 if hp > 0 and hunger_class.data.exhaustion >= 2 then
303 hunger_class.data.exhaustion = 0
305 hunger_class.set_data(player,{exhaustion=hunger_class.data.exhaustion})
309 hunger_class.hp = player:get_hp()
310 hunger_class.drowning = drowning_pointer.get_data(player,{"drowning"}).drowning
311 --make regeneration happen every second
312 if hunger_class.drowning == 0 and hunger_class.data.hunger >= 20 and hunger_class.hp < 20 then -- meta:get_int("on_fire") == 0
313 --print(regeneration_interval,"--------------------------")
314 hunger_class.data.regeneration_interval = hunger_class.data.regeneration_interval + 1
315 if hunger_class.data.regeneration_interval >= 2 then
316 player:set_hp(hunger_class.hp+1)
317 hunger_class.data.exhaustion = hunger_class.data.exhaustion + 32
318 hunger_class.data.regeneration_interval = 0
320 hunger_class.set_data(player,{
321 regeneration_interval = hunger_class.data.regeneration_interval,
322 exhaustion = hunger_class.data.exhaustion ,
323 satiation = hunger_class.data.satiation ,
326 hunger_class.set_data(player,{regeneration_interval=hunger_class.data.regeneration_interval})
328 --reset the regen interval
330 hunger_class.set_data(player,{regeneration_interval=0})
335 minetest.after(0.5, function()
340 minetest.register_on_mods_loaded(function()
341 minetest.after(0,function()
346 --take away hunger and satiation randomly while mining
347 minetest.register_on_dignode(function(pos, oldnode, digger)
348 if digger and digger:is_player() then
349 hunger_class.set_data(digger,{
350 exhaustion = hunger_class.get_data(digger,{"exhaustion"}).exhaustion + math.random(0,2)
355 -- take the eaten food
356 hunger_class.take_food = function(player)
357 hunger_class.data = player:get_wielded_item()
358 hunger_class.data:take_item()
359 player:set_wielded_item(hunger_class.data)
363 hunger_pointer.eat_food = function(player,item)
364 hunger_class.data = hunger_class.get_data(player,{
369 if type(item) == "string" then
370 item = ItemStack(item)
371 elseif type(item) == "table" then
372 item = ItemStack(item.name)
374 item = item:get_name()
376 hunger_class.food_data.satiation = hunger_class.get_group( item, "satiation" )
377 hunger_class.food_data.hunger = hunger_class.get_group( item, "hunger" )
379 hunger_class.data.hunger = hunger_class.data.hunger + hunger_class.food_data.hunger
381 if hunger_class.data.hunger > 20 then
382 hunger_class.data.hunger = 20
386 -- this makes the game easier
387 hunger_class.data.satiation = hunger_class.data.satiation + hunger_class.food_data.satiation
389 hunger_class.set_data(player,{
390 hunger = hunger_class.data.hunger ,
391 satiation = hunger_class.data.satiation,
394 hunger_class.take_food(player)
397 -- easily allows mods to register food
398 minetest.register_food = function(name,def)
399 minetest.register_craftitem(":"..name, {
400 description = def.description,
401 inventory_image = def.texture,
402 groups = {satiation=def.satiation,hunger=def.hunger},
405 minetest.register_node(":"..name.."node", {
406 tiles = {def.texture},
407 drawtype = "allfaces",
412 minetest.register_chatcommand("hungry", {
414 description = "A debug command to test food",
415 privs = {server = true},
416 func = function(name)
417 local player = minetest.get_player_by_name(name)
418 hunger_class.set_data(player,{