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

summaryrefslogtreecommitdiff
path: root/source/game/StarWorldLayout.hpp
blob: ca38ff14dfaa84fef896e94bb5e0bef27e851945 (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#pragma once

#include "StarPerlin.hpp"
#include "StarWeatherTypes.hpp"
#include "StarGameTypes.hpp"
#include "StarCelestialParameters.hpp"

namespace Star {

STAR_STRUCT(Biome);
STAR_STRUCT(TerrainSelector);
STAR_STRUCT(WorldRegion);
STAR_CLASS(WorldLayout);

typedef uint8_t BiomeIndex;
BiomeIndex const NullBiomeIndex = 0;

typedef uint32_t TerrainSelectorIndex;
TerrainSelectorIndex const NullTerrainSelectorIndex = 0;

struct WorldRegionLiquids {
  LiquidId caveLiquid;
  float caveLiquidSeedDensity;

  LiquidId oceanLiquid;
  int oceanLiquidLevel;

  bool encloseLiquids;
  bool fillMicrodungeons;
};

struct WorldRegion {
  WorldRegion();
  explicit WorldRegion(Json const& store);

  Json toJson() const;

  TerrainSelectorIndex terrainSelectorIndex;
  TerrainSelectorIndex foregroundCaveSelectorIndex;
  TerrainSelectorIndex backgroundCaveSelectorIndex;

  BiomeIndex blockBiomeIndex;
  BiomeIndex environmentBiomeIndex;

  List<TerrainSelectorIndex> subBlockSelectorIndexes;
  List<TerrainSelectorIndex> foregroundOreSelectorIndexes;
  List<TerrainSelectorIndex> backgroundOreSelectorIndexes;

  WorldRegionLiquids regionLiquids;
};

class WorldLayout {
public:
  struct BlockNoise {
    static BlockNoise build(Json const& config, uint64_t seed);

    BlockNoise();
    explicit BlockNoise(Json const& store);

    Json toJson() const;

    Vec2I apply(Vec2I const& input, Vec2U const& worldSize) const;

    // Individual noise only applied for horizontal / vertical biome transitions
    PerlinF horizontalNoise;
    PerlinF verticalNoise;

    // 2 dimensional biome noise field for fine grained noise
    PerlinF xNoise;
    PerlinF yNoise;
  };

  struct RegionWeighting {
    float weight;
    int xValue;
    WorldRegion const* region;
  };

  static WorldLayout buildTerrestrialLayout(TerrestrialWorldParameters const& terrestrialParameters, uint64_t seed);
  static WorldLayout buildAsteroidsLayout(AsteroidsWorldParameters const& asteroidParameters, uint64_t seed);
  static WorldLayout buildFloatingDungeonLayout(FloatingDungeonWorldParameters const& floatingDungeonParameters, uint64_t seed);

  WorldLayout();
  WorldLayout(Json const& store);

  Json toJson() const;

  Maybe<BlockNoise> const& blockNoise() const;
  Maybe<PerlinF> const& blendNoise() const;

  List<RectI> playerStartSearchRegions() const;

  BiomeConstPtr const& getBiome(BiomeIndex index) const;
  TerrainSelectorConstPtr const& getTerrainSelector(TerrainSelectorIndex index) const;

  // Will return region weighting in order of greatest to least weighting.
  List<RegionWeighting> getWeighting(int x, int y) const;

  List<RectI> previewAddBiomeRegion(Vec2I const& position, int width) const;
  List<RectI> previewExpandBiomeRegion(Vec2I const& position, int width) const;

  void addBiomeRegion(TerrestrialWorldParameters const& terrestrialParameters, uint64_t seed, Vec2I const& position, String biomeName, String const& subBlockSelector, int width);
  void expandBiomeRegion(Vec2I const& position, int newWidth);

  // sets the environment biome index for all regions in the current layer
  // to the biome at the specified position, and returns the name of the biome
  String setLayerEnvironmentBiome(Vec2I const& position);

  pair<size_t, size_t> findLayerAndCell(int x, int y) const;

private:
  struct WorldLayer {
    WorldLayer();

    int yStart;
    Deque<int> boundaries;
    Deque<WorldRegionPtr> cells;
  };

  struct RegionParams {
    int baseHeight;
    float threatLevel;
    Maybe<String> biomeName;
    Maybe<String> terrainSelector;
    Maybe<String> fgCaveSelector;
    Maybe<String> bgCaveSelector;
    Maybe<String> fgOreSelector;
    Maybe<String> bgOreSelector;
    Maybe<String> subBlockSelector;
    WorldRegionLiquids regionLiquids;
  };

  pair<WorldLayer, List<RectI>> expandRegionInLayer(WorldLayer targetLayer, size_t cellIndex, int newWidth) const;

  BiomeIndex registerBiome(BiomeConstPtr biome);
  TerrainSelectorIndex registerTerrainSelector(TerrainSelectorConstPtr terrainSelector);

  WorldRegion buildRegion(uint64_t seed, RegionParams const& regionParams);
  void addLayer(uint64_t seed, int yStart, RegionParams regionParams);
  void addLayer(uint64_t seed, int yStart, int yBase, String const& primaryBiome,
      RegionParams primaryRegionParams, RegionParams primarySubRegionParams,
      List<RegionParams> secondaryRegions, List<RegionParams> secondarySubRegions,
      Vec2F secondaryRegionSize, Vec2F subRegionSize);
  void finalize(Color mainSkyColor);

  pair<size_t, int> findContainingCell(WorldLayer const& layer, int x) const;
  pair<size_t, int> leftCell(WorldLayer const& layer, size_t cellIndex, int x) const;
  pair<size_t, int> rightCell(WorldLayer const& layer, size_t cellIndex, int x) const;

  Vec2U m_worldSize;

  List<BiomeConstPtr> m_biomes;
  List<TerrainSelectorConstPtr> m_terrainSelectors;

  List<WorldLayer> m_layers;

  float m_regionBlending;
  Maybe<BlockNoise> m_blockNoise;
  Maybe<PerlinF> m_blendNoise;
  List<RectI> m_playerStartSearchRegions;
};

DataStream& operator>>(DataStream& ds, WorldLayout& worldTemplateDescriptor);
DataStream& operator<<(DataStream& ds, WorldLayout& worldTemplateDescriptor);

inline BiomeConstPtr const& WorldLayout::getBiome(BiomeIndex index) const {
  if (index == NullBiomeIndex || index > m_biomes.size())
    throw StarException("WorldLayout::getTerrainSelector called with null or out of range BiomeIndex");
  return m_biomes[index - 1];
}

inline TerrainSelectorConstPtr const& WorldLayout::getTerrainSelector(TerrainSelectorIndex index) const {
  if (index == NullBiomeIndex || index > m_terrainSelectors.size())
    throw StarException("WorldLayout::getTerrainSelector called with null or out of range TerrainSelectorIndex");
  return m_terrainSelectors[index - 1];
}

}