Files
DarkflameServer/dDashboardServer/routes/LevelGating.h
Aaron Kimbrell e213a7aeff feat: web dashboard and playground work
The NexusDashboard-parity dashboard (dDashboardServer) and everything built on it on the experimental branch:
accounts, characters, properties and moderation tools, permissions shared with in-game slash commands, economy
reports, World 3D and property 3D views with client scenery, scheduled events (features, vanity changes, live
events, announcements, restarts), vanity files and events, the CDClient browser, the message inspector with saved
captures, chat filter tools, community challenges, live ops, the AI moderator helper, and the server-side changes
they need.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:43 -05:00

45 lines
1.8 KiB
C++

#pragma once
#include <cstdint>
#include <exception>
#include <map>
#include <sstream>
#include <string>
#include "GeneralUtils.h"
#include "LevelFile.h"
/**
* Which features objects in a scene file (.lvl) are gated on, for the events calendar.
*
* A world server skips an object whose `gatingOnFeature` names a feature that is neither one of the event_1..event_8
* settings nor unlocked for the configured client version in the FeatureGating table (Level::LoadSceneObjects in
* dZoneManager/Level.cpp). Objects are only read when a zone loads, so switching an event on or off changes what a
* zone has only for world instances started afterwards. The file is read by LevelFile (dCommon), as the world reads
* it; client-only objects are left out, as the world skips them. Pure (bytes in, counts out) so it can be unit tested.
*/
namespace LevelGating {
// Feature name -> how many objects in the scene are gated on it, as far as the file could be read
inline std::map<std::string, uint32_t> ReadGatedFeatures(const std::string& lvl) {
std::istringstream stream(lvl);
LevelFile level;
try {
level.Read(stream);
} catch (const std::exception&) {
// A damaged file: keep the objects read before the damage
}
std::map<std::string, uint32_t> features;
for (const auto& object : level.objects) {
const auto setting = [&object](const std::u16string& key) {
const auto it = object.settings.find(key);
return it == object.settings.end() || !it->second ? std::string{} : it->second->GetValueAsString();
};
auto feature = setting(u"gatingOnFeature");
while (!feature.empty() && (feature.back() == '\r' || feature.back() == ' ')) feature.pop_back();
if (feature.empty() || GeneralUtils::TryParse(setting(u"loadOnClientOnly"), false)) continue;
features[feature]++;
}
return features;
}
}