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.
This commit is contained in:
parent
3ce6642a26
commit
4e59fcf5c1
|
@ -785,6 +785,13 @@ core.register_chatcommand("time", {
|
||||||
end,
|
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", {
|
core.register_chatcommand("shutdown", {
|
||||||
description = "shutdown server",
|
description = "shutdown server",
|
||||||
privs = {server=true},
|
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
|
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
|
||||||
* `minetest.get_timeofday()`
|
* `minetest.get_timeofday()`
|
||||||
* `minetest.get_gametime()`: returns the time, in seconds, since the world was created
|
* `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`
|
* `minetest.find_node_near(pos, radius, nodenames)`: returns pos or `nil`
|
||||||
* `radius`: using a maximum metric
|
* `radius`: using a maximum metric
|
||||||
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
* `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)
|
void Environment::setTimeOfDay(u32 time)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(this->m_time_lock);
|
MutexAutoLock lock(this->m_time_lock);
|
||||||
|
if (m_time_of_day > time)
|
||||||
|
m_day_count++;
|
||||||
m_time_of_day = time;
|
m_time_of_day = time;
|
||||||
m_time_of_day_f = (float)time / 24000.0;
|
m_time_of_day_f = (float)time / 24000.0;
|
||||||
}
|
}
|
||||||
|
@ -238,8 +240,10 @@ void Environment::stepTimeOfDay(float dtime)
|
||||||
bool sync_f = false;
|
bool sync_f = false;
|
||||||
if (units > 0) {
|
if (units > 0) {
|
||||||
// Sync at overflow
|
// Sync at overflow
|
||||||
if (m_time_of_day + units >= 24000)
|
if (m_time_of_day + units >= 24000) {
|
||||||
sync_f = true;
|
sync_f = true;
|
||||||
|
m_day_count++;
|
||||||
|
}
|
||||||
m_time_of_day = (m_time_of_day + units) % 24000;
|
m_time_of_day = (m_time_of_day + units) % 24000;
|
||||||
if (sync_f)
|
if (sync_f)
|
||||||
m_time_of_day_f = (float)m_time_of_day / 24000.0;
|
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
|
ABMWithState
|
||||||
*/
|
*/
|
||||||
|
@ -727,6 +738,7 @@ void ServerEnvironment::saveMeta()
|
||||||
args.setU64("lbm_introduction_times_version", 1);
|
args.setU64("lbm_introduction_times_version", 1);
|
||||||
args.set("lbm_introduction_times",
|
args.set("lbm_introduction_times",
|
||||||
m_lbm_mgr.createIntroductionTimesString());
|
m_lbm_mgr.createIntroductionTimesString());
|
||||||
|
args.setU64("day_count", m_day_count);
|
||||||
args.writeLines(ss);
|
args.writeLines(ss);
|
||||||
ss<<"EnvArgsEnd\n";
|
ss<<"EnvArgsEnd\n";
|
||||||
|
|
||||||
|
@ -792,6 +804,12 @@ void ServerEnvironment::loadMeta()
|
||||||
}
|
}
|
||||||
m_lbm_mgr.loadIntroductionTimes(lbm_introduction_times, m_gamedef, m_game_time);
|
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()
|
void ServerEnvironment::loadDefaultMeta()
|
||||||
|
|
|
@ -95,6 +95,8 @@ public:
|
||||||
|
|
||||||
void setDayNightRatioOverride(bool enable, u32 value);
|
void setDayNightRatioOverride(bool enable, u32 value);
|
||||||
|
|
||||||
|
u32 getDayCount();
|
||||||
|
|
||||||
// counter used internally when triggering ABMs
|
// counter used internally when triggering ABMs
|
||||||
u32 m_added_objects;
|
u32 m_added_objects;
|
||||||
|
|
||||||
|
@ -117,6 +119,9 @@ protected:
|
||||||
// Overriding the day-night ratio is useful for custom sky visuals
|
// Overriding the day-night ratio is useful for custom sky visuals
|
||||||
bool m_enable_day_night_ratio_override;
|
bool m_enable_day_night_ratio_override;
|
||||||
u32 m_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
|
* Above: values managed by m_time_lock
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -561,6 +561,15 @@ int ModApiEnvMod::l_get_timeofday(lua_State *L)
|
||||||
return 1;
|
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()
|
// get_gametime()
|
||||||
int ModApiEnvMod::l_get_gametime(lua_State *L)
|
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(set_timeofday);
|
||||||
API_FCT(get_timeofday);
|
API_FCT(get_timeofday);
|
||||||
API_FCT(get_gametime);
|
API_FCT(get_gametime);
|
||||||
|
API_FCT(get_day_count);
|
||||||
API_FCT(find_node_near);
|
API_FCT(find_node_near);
|
||||||
API_FCT(find_nodes_in_area);
|
API_FCT(find_nodes_in_area);
|
||||||
API_FCT(find_nodes_in_area_under_air);
|
API_FCT(find_nodes_in_area_under_air);
|
||||||
|
|
|
@ -113,6 +113,9 @@ private:
|
||||||
// get_gametime()
|
// get_gametime()
|
||||||
static int l_get_gametime(lua_State *L);
|
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
|
// find_node_near(pos, radius, nodenames) -> pos or nil
|
||||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
||||||
static int l_find_node_near(lua_State *L);
|
static int l_find_node_near(lua_State *L);
|
||||||
|
|
Loading…
Reference in New Issue