Skip to content

Commit

Permalink
Worldgen now uses a seed. Fixed #116.
Browse files Browse the repository at this point in the history
  • Loading branch information
Unarelith committed Jul 30, 2020
1 parent 9534c9d commit 03d1a00
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 46 deletions.
3 changes: 3 additions & 0 deletions source/client/states/TitleScreenState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ void TitleScreenState::startSingleplayer(bool showLoadingState, const std::strin
if (m_thread.joinable())
m_thread.join();

const s32 seed = 1337; // FIXME

gk::LogLevel logLevel = gk::LoggerHandler::getInstance().maxLevel();
m_thread = std::thread([this, worldName, logLevel] () {
ServerApplication app{*m_eventHandler};
Expand All @@ -133,6 +135,7 @@ void TitleScreenState::startSingleplayer(bool showLoadingState, const std::strin
app.setLogLevel(logLevel);
app.setSingleplayer(true);
app.setPort(sf::Socket::AnyPort);
app.setSeed(seed);
app.run();
});
}
Expand Down
49 changes: 25 additions & 24 deletions source/common/world/Heightmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,57 +24,58 @@
*
* =====================================================================================
*/
#include "FastNoise.hpp"
#include "Heightmap.hpp"
#include "World.hpp"

void HeightmapChunk::generate() {
FastNoise noise1;
for(int y = 0 ; y < CHUNK_DEPTH ; y++) {
for(int x = 0 ; x < CHUNK_WIDTH ; x++) {
double n1 = m_heightmap.noise1.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
double n2 = m_heightmap.noise2.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
double n3 = m_heightmap.noise3.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
double n4 = m_heightmap.noise4.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
m_map[x + y * CHUNK_WIDTH] = (n1 + (n2 * n3 * (n4 * 2 - 1))) * 64 + 64;
}
}
}

s32 HeightmapChunk::landHeightAt(s8 x, s8 y) const {
return m_map[x + y * CHUNK_WIDTH];
}

void HeightmapChunk::setLandHeight(s8 x, s8 y, s32 height) {
m_map[x + y * CHUNK_WIDTH] = height;
}

Heightmap::Heightmap(s32 seed) {
noise1.SetNoiseType(FastNoise::NoiseType::SimplexFractal);
noise1.SetFrequency(1 / 256.0f);
noise1.SetFractalOctaves(4);
noise1.SetSeed(seed);

FastNoise noise2;
noise2.SetNoiseType(FastNoise::NoiseType::SimplexFractal);
noise2.SetFrequency(1 / 256.0f);
noise2.SetFractalOctaves(4);
noise2.SetSeed(seed);

FastNoise noise3;
noise3.SetNoiseType(FastNoise::NoiseType::SimplexFractal);
noise3.SetFrequency(1 / 256.0f);
noise3.SetFractalOctaves(4);
noise3.SetSeed(seed);

FastNoise noise4;
noise4.SetNoiseType(FastNoise::NoiseType::SimplexFractal);
noise4.SetFractalType(FastNoise::FractalType::Billow);
noise4.SetFrequency(1 / 1024.0f);
noise4.SetFractalOctaves(1);

for(int y = 0 ; y < CHUNK_DEPTH ; y++) {
for(int x = 0 ; x < CHUNK_WIDTH ; x++) {
double n1 = noise1.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
double n2 = noise2.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
double n3 = noise3.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
double n4 = noise4.GetNoise(x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH);
m_map[x + y * CHUNK_WIDTH] = (n1 + (n2 * n3 * (n4 * 2 - 1))) * 64 + 64;
}
}
}

s32 HeightmapChunk::landHeightAt(s8 x, s8 y) const {
return m_map[x + y * CHUNK_WIDTH];
}

void HeightmapChunk::setLandHeight(s8 x, s8 y, s32 height) {
m_map[x + y * CHUNK_WIDTH] = height;
noise4.SetSeed(seed);
}

HeightmapChunk &Heightmap::getOrCreateChunk(s32 chunkX, s32 chunkY) {
HeightmapChunk *chunk = nullptr;

auto it = m_chunks.find({chunkX, chunkY});
if (it == m_chunks.end()) {
m_chunks.emplace(gk::Vector2i{chunkX, chunkY}, HeightmapChunk{chunkX, chunkY});
m_chunks.emplace(gk::Vector2i{chunkX, chunkY}, HeightmapChunk{*this, chunkX, chunkY});

chunk = &m_chunks.at({chunkX, chunkY});
chunk->generate();
Expand Down
16 changes: 14 additions & 2 deletions source/common/world/Heightmap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@
#include <gk/core/Vector2.hpp>

#include "EngineConfig.hpp"
#include "FastNoise.hpp"

class Heightmap;

class HeightmapChunk {
public:
HeightmapChunk(s32 x, s32 y)
: m_x(x), m_y(y) {
HeightmapChunk(Heightmap &heightmap, s32 x, s32 y)
: m_heightmap(heightmap), m_x(x), m_y(y) {
std::memset(m_map, 0, CHUNK_WIDTH * CHUNK_DEPTH * sizeof(s32));
}

Expand All @@ -48,6 +51,8 @@ class HeightmapChunk {
void setLandHeight(s8 x, s8 y, s32 height);

private:
Heightmap &m_heightmap;

s32 m_x = 0;
s32 m_y = 0;

Expand All @@ -56,11 +61,18 @@ class HeightmapChunk {

class Heightmap {
public:
Heightmap(s32 seed);

HeightmapChunk &getOrCreateChunk(s32 chunkX, s32 chunkY);

int getHighestBlockAt(s32 blockX, s32 blockY);
int getHighestChunkAt(s32 blockX, s32 blockY);

FastNoise noise1;
FastNoise noise2;
FastNoise noise3;
FastNoise noise4;

private:
std::unordered_map<gk::Vector2i, HeightmapChunk> m_chunks;
};
Expand Down
2 changes: 1 addition & 1 deletion source/server/core/ServerApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ bool ServerApplication::init() {
m_serverCommandHandler.setupCallbacks();

m_worldController.setServer(m_serverCommandHandler);
m_worldController.init(m_players);
m_worldController.init(m_players, m_seed);

m_scriptEngine.luaCore().setRegistry(&m_registry);

Expand Down
3 changes: 3 additions & 0 deletions source/server/core/ServerApplication.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ServerApplication {
void setPort(u16 port) { m_port = port; }
void setWorldName(const std::string &worldName) { m_worldName = worldName; }
void setLogLevel(gk::LogLevel logLevel) { m_loggerHandler.setMaxLevel(logLevel); }
void setSeed(s32 seed) { m_seed = seed; }

private:
void update();
Expand All @@ -77,6 +78,8 @@ class ServerApplication {

Server m_server;
ServerCommandHandler m_serverCommandHandler{m_scriptEngine, m_server, m_worldController, m_players, m_registry};

s32 m_seed = 1337; // FIXME
};

#endif // SERVERAPPLICATION_HPP_
11 changes: 11 additions & 0 deletions source/server/world/ServerWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@
#include "ServerPlayer.hpp"
#include "ServerWorld.hpp"

ServerWorld::ServerWorld(PlayerList &players, const Dimension &dimension, gk::GameClock &clock, s32 seed)
: m_players(players),
m_dimension(dimension),
m_heightmap(seed),
m_terrainGenerator(m_heightmap, dimension, seed),
m_clock(clock),
m_scene(players),
m_seed(seed)
{
}

void ServerWorld::update(bool doTick) {
for (auto &it : m_chunks) {
if (doTick)
Expand Down
7 changes: 5 additions & 2 deletions source/server/world/ServerWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ class ServerWorld : public World {
using ChunkMap = std::unordered_map<gk::Vector3i, std::unique_ptr<ServerChunk>>;

public:
ServerWorld(PlayerList &players, const Dimension &dimension, gk::GameClock &clock)
: m_players(players), m_dimension(dimension), m_terrainGenerator(m_heightmap, dimension), m_clock(clock), m_scene(players) {}
ServerWorld(PlayerList &players, const Dimension &dimension, gk::GameClock &clock, s32 seed);

void update(bool doTick);

Expand All @@ -75,6 +74,8 @@ class ServerWorld : public World {

void setServer(ServerCommandHandler *server) { m_server = server; m_scene.setServer(server); }

s32 seed() const { return m_seed; }

static void initUsertype(sol::state &lua);

private:
Expand All @@ -92,6 +93,8 @@ class ServerWorld : public World {
gk::GameClock &m_clock;

ServerScene m_scene;

s32 m_seed = 0;
};

#endif // SERVERWORLD_HPP_
4 changes: 2 additions & 2 deletions source/server/world/TerrainBiomeSampler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
#include "ServerWorld.hpp"
#include "TerrainBiomeSampler.hpp"

TerrainBiomeSampler::TerrainBiomeSampler(const Dimension &dimension) : m_dimension(dimension) {
TerrainBiomeSampler::TerrainBiomeSampler(const Dimension &dimension, s32 seed) : m_dimension(dimension) {
for (u8 i = 0; i < biomeParamCount; i++) {
m_paramNoises.emplace_back();

m_paramNoises.back().SetNoiseType(FastNoise::NoiseType::SimplexFractal);
m_paramNoises.back().SetFrequency(1 / 800.0f);
m_paramNoises.back().SetFractalOctaves(5);
m_paramNoises.back().SetSeed(i);
m_paramNoises.back().SetSeed(seed + i);
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/server/world/TerrainBiomeSampler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Dimension;

class TerrainBiomeSampler {
public:
TerrainBiomeSampler(const Dimension &dimension);
TerrainBiomeSampler(const Dimension &dimension, s32 seed);

u16 getBiomeIndexAt(s32 x, s32 y) const;

Expand Down
20 changes: 12 additions & 8 deletions source/server/world/TerrainGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@
#include <glm/gtc/noise.hpp>
#include "FastNoise.hpp"

TerrainGenerator::TerrainGenerator(Heightmap &heightmap, const Dimension &dimension, s32 seed)
: m_biomeSampler(dimension, seed), m_heightmap(heightmap)
{
m_caveNoise.SetFrequency(1.0 / 128.0);
m_caveNoise.SetFractalOctaves(2);
m_caveNoise.SetSeed(seed);
}

void TerrainGenerator::generate(ServerChunk &chunk) const {
fastNoiseGeneration(chunk);
}
Expand Down Expand Up @@ -78,7 +86,7 @@ void TerrainGenerator::fastNoiseGeneration(ServerChunk &chunk) const {
chunk.setBlockRaw(x, y, z, biome.getDeepBlockID());

// Caves
generateCaves(chunk, x, y, z, h, heightmap);
generateCaves(chunk, x, y, z);

// Populate ores.
generateOres(chunk, x, y, z, biome, rand);
Expand Down Expand Up @@ -275,18 +283,14 @@ inline void TerrainGenerator::generateCavesOld(ServerChunk &chunk, int x, int y,
}
}

inline void TerrainGenerator::generateCaves(ServerChunk &chunk, int x, int y, int z, int h, HeightmapChunk &heightmap) const {
static FastNoise noise;
noise.SetFrequency(1.0 / 128.0);
noise.SetFractalOctaves(2);

inline void TerrainGenerator::generateCaves(ServerChunk &chunk, int x, int y, int z) const {
int rx = x + chunk.x() * CHUNK_WIDTH;
int ry = y + chunk.y() * CHUNK_DEPTH;
int rz = z + chunk.z() * CHUNK_HEIGHT;

// Density map (not textured image)
double n1 = noise.GetSimplexFractal(rx, ry, rz);
double n2 = noise.GetSimplexFractal(rx, ry + 88.0, rz);
double n1 = m_caveNoise.GetSimplexFractal(rx, ry, rz);
double n2 = m_caveNoise.GetSimplexFractal(rx, ry + 88.0, rz);
double finalNoise = n1 * n1 + n2 * n2;

if (finalNoise < 0.02) {
Expand Down
7 changes: 4 additions & 3 deletions source/server/world/TerrainGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ class ServerChunk;

class TerrainGenerator {
public:
TerrainGenerator(Heightmap &heightmap, const Dimension &dimension)
: m_biomeSampler(dimension), m_heightmap(heightmap) {}
TerrainGenerator(Heightmap &heightmap, const Dimension &dimension, s32 seed);

void generate(ServerChunk &chunk) const;

Expand All @@ -58,7 +57,7 @@ class TerrainGenerator {

void generateOres(ServerChunk &chunk, int x, int y, int z, const Biome &biome, Random_t &rand) const;
void generateCavesOld(ServerChunk &chunk, int x, int y, int z, int h, HeightmapChunk &heightmap) const;
void generateCaves(ServerChunk &chunk, int x, int y, int z, int h, HeightmapChunk &heightmap) const;
void generateCaves(ServerChunk &chunk, int x, int y, int z) const;

void randomWalkOrePlace(ServerChunk &chunk, int x, int y, int z, Random_t &rand, u16 oreBlock, u16 deepBlock, int size) const;
void oreFloodFill(ServerChunk &chunk, double x, double y, double z, u16 toReplace, u16 replaceWith, int depth, Random_t &rand) const;
Expand All @@ -69,6 +68,8 @@ class TerrainGenerator {
TerrainBiomeSampler m_biomeSampler;

Heightmap &m_heightmap;

FastNoise m_caveNoise;
};

#endif // TERRAINGENERATOR_HPP_
4 changes: 2 additions & 2 deletions source/server/world/WorldController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
#include "WorldController.hpp"
#include "WorldSaveBasicBackend.hpp"

void WorldController::init(PlayerList &players) {
void WorldController::init(PlayerList &players, s32 seed) {
for (const Dimension &dimension : m_registry.dimensions()) {
m_worldList.emplace_back(players, dimension, m_clock);
m_worldList.emplace_back(players, dimension, m_clock, seed);
m_worldList.back().setServer(m_server);
}

Expand Down
2 changes: 1 addition & 1 deletion source/server/world/WorldController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class WorldController {
WorldController(Registry &registry, gk::GameClock &clock)
: m_registry(registry), m_clock(clock) {}

void init(PlayerList &players);
void init(PlayerList &players, s32 seed);

void clearEntities();

Expand Down

0 comments on commit 03d1a00

Please sign in to comment.