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

summaryrefslogtreecommitdiff
path: root/source/game/StarLiquidsDatabase.cpp
blob: 0ef03ae5c6d5ae1f4f9189ce02c845a4964eada9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#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<LiquidSettings>();
      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<MaterialId>(materialDatabase->materialId(*materialResult));
        else if (auto liquidResult = interaction.optUInt("liquidResult"))
          interactionResult = makeRight<LiquidId>(*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<LiquidSettingsConstPtr> LiquidsDatabase::allLiquidSettings() const {
  return filtered<List<LiquidSettingsConstPtr>>(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<String> LiquidsDatabase::liquidPath(LiquidId liquidId) const {
  if (liquidId == EmptyLiquidId)
    return {};
  else if (auto settings = liquidSettings(liquidId))
    return settings->path;
  return {};
}

Maybe<Json> LiquidsDatabase::liquidConfig(LiquidId liquidId) const {
  if (liquidId == EmptyLiquidId)
    return {};
  else if (auto settings = liquidSettings(liquidId))
    return settings->config;
  return {};
}

Maybe<LiquidInteractionResult> LiquidsDatabase::interact(LiquidId target, LiquidId other) const {
  if (auto settings = liquidSettings(target))
    return settings->interactions.value(other);
  return {};
}

}