Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarTenantDatabase.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarTenantDatabase.cpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/game/StarTenantDatabase.cpp')
-rw-r--r--source/game/StarTenantDatabase.cpp103
1 files changed, 103 insertions, 0 deletions
diff --git a/source/game/StarTenantDatabase.cpp b/source/game/StarTenantDatabase.cpp
new file mode 100644
index 0000000..3397bd7
--- /dev/null
+++ b/source/game/StarTenantDatabase.cpp
@@ -0,0 +1,103 @@
+#include "StarTenantDatabase.hpp"
+#include "StarJsonExtra.hpp"
+
+namespace Star {
+
+bool Tenant::criteriaSatisfied(StringMap<unsigned> const& colonyTags) const {
+ // Check whether colonyTags is a supermultiset of colonyTagCriteria
+ for (pair<String, unsigned> const& entry : colonyTagCriteria.pairs()) {
+ if (colonyTags.value(entry.first, 0) < entry.second)
+ return false;
+ }
+ return true;
+}
+
+TenantDatabase::TenantDatabase() {
+ auto assets = Root::singleton().assets();
+
+ auto files = assets->scanExtension("tenant");
+ assets->queueJsons(files);
+ for (auto file : files) {
+ try {
+ String name = assets->json(file).getString("name");
+ if (m_paths.contains(name))
+ Logger::error("Tenant %s defined twice, second time from %s", name, file);
+ else
+ m_paths[name] = file;
+ } catch (std::exception const& e) {
+ Logger::error("Error loading tenant file %s: %s", file, outputException(e, true));
+ }
+ }
+}
+
+void TenantDatabase::cleanup() {
+ MutexLocker locker(m_cacheMutex);
+ m_tenantCache.cleanup();
+}
+
+TenantPtr TenantDatabase::getTenant(String const& name) const {
+ MutexLocker locker(m_cacheMutex);
+ return m_tenantCache.get(name,
+ [this](String const& name) -> TenantPtr {
+ if (auto path = m_paths.maybe(name))
+ return readTenant(*path);
+ throw TenantException::format("No such tenant named '%s'", name);
+ });
+}
+
+List<TenantPtr> TenantDatabase::getMatchingTenants(StringMap<unsigned> const& colonyTags) const {
+ // This implementation loops over every tenant. Smarter implementations could
+ // be written if it becomes a bottleneck, depending on how colonyTags end up
+ // being
+ // used, how many there are, how many tenants have similar criteria, etc.
+ List<TenantPtr> matchingTenants;
+ for (String const& name : m_paths.keys()) {
+ TenantPtr tenant = getTenant(name);
+ if (tenant->criteriaSatisfied(colonyTags))
+ matchingTenants.append(tenant);
+ }
+ return matchingTenants;
+}
+
+TenantPtr TenantDatabase::readTenant(String const& path) {
+ try {
+ auto assets = Root::singleton().assets();
+ Json config = assets->json(path);
+
+ String name = config.getString("name");
+ float priority = config.getFloat("priority");
+
+ StringMap<unsigned> colonyTagCriteria;
+ for (pair<String, Json> const& entry : config.getObject("colonyTagCriteria").pairs()) {
+ colonyTagCriteria[entry.first] = entry.second.toUInt();
+ }
+
+ List<TenantSpawnable> tenants = config.getArray("tenants").transformed([](Json const& json) -> TenantSpawnable {
+ String spawn = json.getString("spawn");
+ if (spawn == "monster") {
+ return TenantMonsterSpawnable{json.getString("type"), json.optFloat("level"), json.opt("overrides")};
+ } else {
+ starAssert(json.getString("spawn") == "npc");
+
+ Json speciesJson = json.get("species");
+ List<String> species;
+ if (speciesJson.isType(Json::Type::Array))
+ species = speciesJson.toArray().transformed(mem_fn(&Json::toString));
+ else
+ species.append(speciesJson.toString());
+
+ return TenantNpcSpawnable{species, json.getString("type"), json.optFloat("level"), json.opt("overrides")};
+ }
+ });
+
+ Maybe<TenantRent> rent = config.opt("rent").apply([](Json const& json) {
+ return TenantRent{jsonToVec2F(json.get("periodRange")), json.getString("pool")};
+ });
+
+ return make_shared<Tenant>(Tenant{name, priority, colonyTagCriteria, tenants, rent, config});
+ } catch (std::exception const& e) {
+ throw TenantException::format("Error loading tenant '%s': %s", path, outputException(e, false));
+ }
+}
+
+}