Convert HHmm to Fallout game-hour float
Add parsing and application of HHmm time strings as Fallout game-hour floats so GUI time presets apply correctly. Introduce ParseHHmmToGameHour in plugin/src/F4TWorldStateSync.cpp and use it when building the console command (formats as set gamehour to <float> with fallback to the raw HHmm string if parsing fails). Improve logging to indicate when a parsed HHmm was used. Update protocol/server-world-state.md, changelog.md, and docs/dev-log.md to document the behavior and rationale.
This commit is contained in:
@@ -195,6 +195,47 @@ namespace
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<float> ParseHHmmToGameHour(std::string_view a_hhmm)
|
||||
{
|
||||
if (a_hhmm.empty() || a_hhmm.size() > 4) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string digits;
|
||||
digits.reserve(4);
|
||||
for (const auto ch : a_hhmm) {
|
||||
if (ch < '0' || ch > '9') {
|
||||
return std::nullopt;
|
||||
}
|
||||
digits.push_back(ch);
|
||||
}
|
||||
|
||||
while (digits.size() < 4) {
|
||||
digits.insert(digits.begin(), '0');
|
||||
}
|
||||
|
||||
int hours = 0;
|
||||
int minutes = 0;
|
||||
{
|
||||
const auto* begin = digits.data();
|
||||
const auto* split = begin + 2;
|
||||
const auto* end = begin + 4;
|
||||
|
||||
const auto hourResult = std::from_chars(begin, split, hours);
|
||||
const auto minuteResult = std::from_chars(split, end, minutes);
|
||||
if (hourResult.ec != std::errc{} || hourResult.ptr != split ||
|
||||
minuteResult.ec != std::errc{} || minuteResult.ptr != end) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return static_cast<float>(hours) + static_cast<float>(minutes) / 60.0F;
|
||||
}
|
||||
|
||||
bool ForceHostWorldStateBroadcast(std::optional<std::uint32_t> a_forcedWeatherFormId, bool a_sendTime)
|
||||
{
|
||||
if (!F4T::WorldStateSync::IsWorldStateHost() || !F4T::Networking::IsConnectedToServer()) {
|
||||
@@ -394,7 +435,10 @@ namespace
|
||||
void ApplyServerWorldState(const F4T::WorldStateSync::PendingServerWorldState& a_state)
|
||||
{
|
||||
if (a_state.timeHHmm && !a_state.timeHHmm->empty()) {
|
||||
const auto command = std::format("set gamehour to {}", *a_state.timeHHmm);
|
||||
const auto parsedGameHour = ParseHHmmToGameHour(*a_state.timeHHmm);
|
||||
const auto command = parsedGameHour
|
||||
? std::format("set gamehour to {:.4f}", *parsedGameHour)
|
||||
: std::format("set gamehour to {}", *a_state.timeHHmm);
|
||||
RE::Console::ExecuteCommand(command.c_str());
|
||||
|
||||
float gameHour = 0.0F;
|
||||
@@ -415,7 +459,14 @@ namespace
|
||||
}
|
||||
|
||||
if (ShouldLog("server_world_state_time_apply")) {
|
||||
LogInfo(std::format("Applied server time command: {}", command));
|
||||
if (parsedGameHour) {
|
||||
LogInfo(std::format(
|
||||
"Applied server time command: {} (from HHmm={}).",
|
||||
command,
|
||||
*a_state.timeHHmm));
|
||||
} else {
|
||||
LogInfo(std::format("Applied server time command: {}", command));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user