137 lines
4.0 KiB
Lua

local MOD_NAME = minetest.get_current_modname() or "exertion";
local MOD_PATH = minetest.get_modpath(MOD_NAME);
local exertion = { MOD_NAME = MOD_NAME, MOD_PATH = MOD_PATH };
_G[MOD_NAME] = exertion;
local function callFile(fileName, ...)
local chunk, err = loadfile(MOD_PATH .. "/" .. fileName);
if not chunk then error(err); end;
return chunk(...);
end;
local settings = callFile("loadSettings.lua", exertion);
exertion.settings = settings;
local PlayerState = callFile("PlayerState.lua", exertion);
exertion.PlayerState = PlayerState;
PlayerState.load();
local playerStates = {};
--- Retrieves the PlayerState object for a given player. Returns nil if player
-- is not logged in.
--
-- @param player
-- A player object or player name.
--
function exertion.getPlayerState(player)
if type(player) == 'string' then
player = minetest.get_player_by_name(player);
end;
return playerStates[player];
end;
minetest.register_on_joinplayer(
function(player)
minetest.after(
0, function() playerStates[player] = PlayerState(player); end);
end);
minetest.register_on_leaveplayer(
function(player)
playerStates[player] = nil;
end);
minetest.register_on_dieplayer(
function(player)
local ps = playerStates[player];
if not ps then return; end;
ps:setFed(0, true);
ps:setHydrated(0, true);
ps:setPoisoned(0, true);
ps:clearExertionStats();
ps:updateHud();
end);
minetest.register_on_shutdown(PlayerState.save);
minetest.register_on_dignode(
function(pos, oldNode, digger)
local ps = playerStates[digger];
if ps then ps:markBuildAction(oldNode); end;
end);
minetest.register_on_placenode(
function(pos, newNode, placer, oldNode, itemStack, pointedThing)
local ps = playerStates[placer];
if ps then ps:markBuildAction(newNode); end;
end);
local controlPeriod = settings.controlTestPeriod_seconds;
local updatePeriod = settings.accountingPeriod_seconds;
local savePeriod = settings.savePeriod_seconds;
local controlTime = 0.0;
local updateTime = 0.0;
local saveTime = 0.0;
minetest.register_globalstep(
function(dt)
controlTime = controlTime + dt;
if controlTime >= controlPeriod then
for _, ps in pairs(playerStates) do
ps:pollForActivity();
end;
controlTime = 0;
end;
updateTime = updateTime + dt;
if updateTime >= updatePeriod then
controlPeriod = settings.controlTestPeriod_seconds;
updatePeriod = settings.accountingPeriod_seconds;
local tw = os.time();
for _, ps in pairs(playerStates) do
ps:update(tw, updateTime);
end;
updateTime = 0;
end;
saveTime = saveTime + dt;
if saveTime >= savePeriod then
savePeriod = settings.savePeriod_seconds;
PlayerState.save();
saveTime = 0;
end;
end);
minetest.register_on_item_eat(
function(hpChange, replacementItem, itemStack, player, pointedThing)
if itemStack:take_item() ~= nil then
local ps = playerStates[player];
if ps then
if hpChange > 0 then
local pp = math.max(0, settings.foodPoisoningProb);
if math.random() <= 1.0 - pp then
local update = false;
update = ps:addFood(hpChange, true) or update;
update = ps:addWater(hpChange / 2, true) or update;
if update then ps:updateHud(); end;
else
minetest.chat_send_player(player:get_player_name(),
settings.foodPoisoningMessage);
ps:addPoison(hpChange);
end;
elseif hpChange < 0 then
minetest.chat_send_player(player:get_player_name(),
settings.foodPoisoningMessage);
ps:addPoison(-hpChange);
end;
end;
itemStack:add_item(replacementItem);
end;
return itemStack;
end);