#include "StarLiquidsDatabase.hpp" #include "StarLexicalCast.hpp" #include "StarAssets.hpp" #include "StarJsonExtra.hpp" #include "StarMaterialDatabase.hpp" #include "StarRoot.hpp" namespace Star { LiquidSettings::LiquidSettings() : id(EmptyLiquidId) {} LiquidsDatabase::LiquidsDatabase() { auto assets = Root::singleton().assets(); auto materialDatabase = Root::singleton().materialDatabase(); auto config = assets->json("/liquids.config"); auto liquidEngineParameters = config.get("liquidEngineParameters"); m_liquidEngineParameters.lateralMoveFactor = liquidEngineParameters.getFloat("lateralMoveFactor"); m_liquidEngineParameters.spreadOverfillUpFactor = liquidEngineParameters.getFloat("spreadOverfillUpFactor"); m_liquidEngineParameters.spreadOverfillLateralFactor = liquidEngineParameters.getFloat("spreadOverfillLateralFactor"); m_liquidEngineParameters.spreadOverfillDownFactor = liquidEngineParameters.getFloat("spreadOverfillDownFactor"); m_liquidEngineParameters.pressureEqualizeFactor = liquidEngineParameters.getFloat("pressureEqualizeFactor"); m_liquidEngineParameters.pressureMoveFactor = liquidEngineParameters.getFloat("pressureMoveFactor"); m_liquidEngineParameters.maximumPressureLevelImbalance = liquidEngineParameters.getFloat("maximumPressureLevelImbalance"); m_liquidEngineParameters.minimumLivenPressureChange = liquidEngineParameters.getFloat("minimumLivenPressureChange"); m_liquidEngineParameters.minimumLivenLevelChange = liquidEngineParameters.getFloat("minimumLivenLevelChange"); m_liquidEngineParameters.minimumLiquidLevel = liquidEngineParameters.getFloat("minimumLiquidLevel"); m_liquidEngineParameters.interactTransformationLevel = liquidEngineParameters.getFloat("interactTransformationLevel"); m_backgroundDrain = config.getFloat("backgroundDrain"); m_liquidNames["empty"] = EmptyLiquidId; auto& liquids = assets->scanExtension("liquid"); assets->queueJsons(liquids); for (auto& file : liquids) { try { auto liquidConfig = assets->json(file); unsigned id = liquidConfig.getUInt("liquidId"); if (id != (LiquidId)id) throw LiquidException(strf("Liquid id {} does not fall in the valid range, wrapped to {}\n", id, (LiquidId)id)); auto entry = make_shared(); entry->id = (LiquidId)id; entry->name = liquidConfig.getString("name"); entry->path = file; entry->config = liquidConfig; JsonObject descriptions; for (auto pair : liquidConfig.iterateObject()) if (pair.first.endsWith("Description")) descriptions[pair.first] = pair.second; descriptions["description"] = liquidConfig.getString("description", ""); entry->descriptions = descriptions; entry->tickDelta = liquidConfig.getUInt("tickDelta"); entry->liquidColor = jsonToVec4B(liquidConfig.get("color")); if (liquidConfig.contains("radiantLight")) { auto lightLevel = jsonToVec3B(liquidConfig.get("radiantLight")); entry->radiantLightLevel = Color::rgb(lightLevel).toRgbF(); } entry->itemDrop = ItemDescriptor(liquidConfig.get("itemDrop", {})); entry->statusEffects = liquidConfig.getArray("statusEffects", {}); for (auto const& interaction : liquidConfig.getArray("interactions", {})) { LiquidId liquid = interaction.getUInt("liquid"); LiquidInteractionResult interactionResult; if (auto materialResult = interaction.optString("materialResult")) interactionResult = makeLeft(materialDatabase->materialId(*materialResult)); else if (auto liquidResult = interaction.optUInt("liquidResult")) interactionResult = makeRight(*liquidResult); else throw LiquidException::format( "Neither resultMaterial or resultLiquid specified in liquid interaction of liquid {}", entry->id); entry->interactions[liquid] = interactionResult; } m_settings.set(entry->id, entry); m_liquidNames.add(entry->name, entry->id); } catch (StarException const& e) { throw LiquidException(strf("Error loading liquid file {}", file), e); } } } LiquidCellEngineParameters LiquidsDatabase::liquidEngineParameters() const { return m_liquidEngineParameters; } StringList LiquidsDatabase::liquidNames() const { return m_liquidNames.keys(); } List LiquidsDatabase::allLiquidSettings() const { return filtered>(m_settings, mem_fn(&LiquidSettingsConstPtr::operator bool)); } LiquidId LiquidsDatabase::liquidId(String const& str) const { return m_liquidNames.get(str); } String LiquidsDatabase::liquidName(LiquidId liquidId) const { if (liquidId == EmptyLiquidId) return "empty"; else if (auto settings = liquidSettings(liquidId)) return settings->name; throw LiquidException::format("invalid liquid id {}", liquidId); } String LiquidsDatabase::liquidDescription(LiquidId liquidId, String const& species) const { if (liquidId == EmptyLiquidId) return String(); else if (auto settings = liquidSettings(liquidId)) return settings->descriptions.getString( strf("{}Description", species), settings->descriptions.getString("description")); throw LiquidException::format("invalid liquid id {}", liquidId); } String LiquidsDatabase::liquidDescription(LiquidId liquidId) const { if (liquidId == EmptyLiquidId) return String(); else if (auto settings = liquidSettings(liquidId)) return settings->descriptions.getString("description"); throw LiquidException::format("invalid liquid id {}", liquidId); } Maybe LiquidsDatabase::liquidPath(LiquidId liquidId) const { if (liquidId == EmptyLiquidId) return {}; else if (auto settings = liquidSettings(liquidId)) return settings->path; return {}; } Maybe LiquidsDatabase::liquidConfig(LiquidId liquidId) const { if (liquidId == EmptyLiquidId) return {}; else if (auto settings = liquidSettings(liquidId)) return settings->config; return {}; } Maybe LiquidsDatabase::interact(LiquidId target, LiquidId other) const { if (auto settings = liquidSettings(target)) return settings->interactions.value(other); return {}; } }