Skip to content
Snippets Groups Projects
Commit 4e59fcf5 authored by Auke Kok's avatar Auke Kok Committed by est31
Browse files

Add consistent monotonic day counter - get_day_count()

I've written several experimental bits of code that revolve around the
need for a consistent calendar, but implementing one is extremely hard
in mods due to time changes and mods overriding core.get_timeofday(),
which will conflict.

The second part of the problem is that doing this from a mod requires
constant maintenance of a settings file.

An implementation in core is trivial, however, and solves all of
these problems at virtually no cost: No extra branches in server
steps, and a single branch when minetest.set_time_of_day(), which is
entirely reasonable.

We store the day_count value in env_meta.txt.

The use case is obvious: This change allows mods to create an actual
virtual calendar, or properly account for seasonal changes, etc..

We add a "/days" chatcommand that displays the current day count. No
permissions are needed. It can only retrieve the day count, not
modify it.
parent 3ce6642a
No related branches found
No related tags found
No related merge requests found
......@@ -785,6 +785,13 @@ core.register_chatcommand("time", {
end,
})
core.register_chatcommand("days", {
description = "Display day count",
func = function(name, param)
return true, "Current day is " .. core.get_day_count()
end
})
core.register_chatcommand("shutdown", {
description = "shutdown server",
privs = {server=true},
......
......@@ -1998,6 +1998,8 @@ and `minetest.auth_reload` call the authetification handler.
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
* `minetest.get_timeofday()`
* `minetest.get_gametime()`: returns the time, in seconds, since the world was created
* `minetest.get_day_count()`: returns number days elapsed since world was created,
* accounting for time changes.
* `minetest.find_node_near(pos, radius, nodenames)`: returns pos or `nil`
* `radius`: using a maximum metric
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
......
......@@ -208,6 +208,8 @@ void Environment::setDayNightRatioOverride(bool enable, u32 value)
void Environment::setTimeOfDay(u32 time)
{
MutexAutoLock lock(this->m_time_lock);
if (m_time_of_day > time)
m_day_count++;
m_time_of_day = time;
m_time_of_day_f = (float)time / 24000.0;
}
......@@ -238,8 +240,10 @@ void Environment::stepTimeOfDay(float dtime)
bool sync_f = false;
if (units > 0) {
// Sync at overflow
if (m_time_of_day + units >= 24000)
if (m_time_of_day + units >= 24000) {
sync_f = true;
m_day_count++;
}
m_time_of_day = (m_time_of_day + units) % 24000;
if (sync_f)
m_time_of_day_f = (float)m_time_of_day / 24000.0;
......@@ -256,6 +260,13 @@ void Environment::stepTimeOfDay(float dtime)
}
}
u32 Environment::getDayCount()
{
// Atomic<u32> counter
return m_day_count;
}
/*
ABMWithState
*/
......@@ -727,6 +738,7 @@ void ServerEnvironment::saveMeta()
args.setU64("lbm_introduction_times_version", 1);
args.set("lbm_introduction_times",
m_lbm_mgr.createIntroductionTimesString());
args.setU64("day_count", m_day_count);
args.writeLines(ss);
ss<<"EnvArgsEnd\n";
......@@ -792,6 +804,12 @@ void ServerEnvironment::loadMeta()
}
m_lbm_mgr.loadIntroductionTimes(lbm_introduction_times, m_gamedef, m_game_time);
try {
m_day_count = args.getU64("day_count");
} catch (SettingNotFoundException &e) {
// If missing, start the day counter
m_day_count = 0;
}
}
void ServerEnvironment::loadDefaultMeta()
......
......@@ -95,6 +95,8 @@ class Environment
void setDayNightRatioOverride(bool enable, u32 value);
u32 getDayCount();
// counter used internally when triggering ABMs
u32 m_added_objects;
......@@ -117,6 +119,9 @@ class Environment
// Overriding the day-night ratio is useful for custom sky visuals
bool m_enable_day_night_ratio_override;
u32 m_day_night_ratio_override;
// Days from the server start, accounts for time shift
// in game (e.g. /time or bed usage)
Atomic<u32> m_day_count;
/*
* Above: values managed by m_time_lock
*/
......
......@@ -561,6 +561,15 @@ int ModApiEnvMod::l_get_timeofday(lua_State *L)
return 1;
}
// get_day_count() -> int
int ModApiEnvMod::l_get_day_count(lua_State *L)
{
GET_ENV_PTR;
lua_pushnumber(L, env->getDayCount());
return 1;
}
// get_gametime()
int ModApiEnvMod::l_get_gametime(lua_State *L)
{
......@@ -1055,6 +1064,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
API_FCT(set_timeofday);
API_FCT(get_timeofday);
API_FCT(get_gametime);
API_FCT(get_day_count);
API_FCT(find_node_near);
API_FCT(find_nodes_in_area);
API_FCT(find_nodes_in_area_under_air);
......
......@@ -113,6 +113,9 @@ class ModApiEnvMod : public ModApiBase {
// get_gametime()
static int l_get_gametime(lua_State *L);
// get_day_count() -> int
static int l_get_day_count(lua_State *L);
// find_node_near(pos, radius, nodenames) -> pos or nil
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
static int l_find_node_near(lua_State *L);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment