feat: environment is primary

This commit is contained in:
MihailRis 2026-05-16 22:24:35 +03:00
parent 4aaa5b2d7e
commit 3476bddc6b
10 changed files with 60 additions and 29 deletions

View file

@ -25,7 +25,7 @@ const uint MIN_SURROUNDING = 9;
ChunksController::ChunksController(Level& level) ChunksController::ChunksController(Level& level)
: level(level), : level(level),
generator(std::make_unique<WorldGenerator>( generator(std::make_unique<WorldGenerator>(
level.content.generators.require(level.getWorld()->getGenerator()), level.content.generators.require(level.environment.generator),
level.content, level.content,
level.getWorld()->getSeed() level.getWorld()->getSeed()
)) {} )) {}

View file

@ -179,7 +179,7 @@ void EngineController::onMissingContent(
if (engine.isHeadless()) { if (engine.isHeadless()) {
throw std::runtime_error( throw std::runtime_error(
"missing content: " + "missing content: " +
json::stringify(create_missing_content_report(report), true, " ") util::quote(json::stringify(create_missing_content_report(report), true, " "))
); );
} else { } else {
engine.setScreen(std::make_shared<MenuScreen>(engine)); engine.setScreen(std::make_shared<MenuScreen>(engine));
@ -268,7 +268,7 @@ inline uint64_t str2seed(const std::string& seedstr) {
void EngineController::createWorld( void EngineController::createWorld(
const std::string& name, const std::string& name,
const std::string& seedstr, const std::string& seedstr,
const std::string& generatorID const std::string& environment
) { ) {
uint64_t seed = str2seed(seedstr); uint64_t seed = str2seed(seedstr);
@ -279,17 +279,31 @@ void EngineController::createWorld(
paths.setCurrentWorldFolder(folder); paths.setCurrentWorldFolder(folder);
engine.getContentControl().loadContent(); engine.getContentControl().loadContent();
}); });
const auto& generators = engine.getContentControl().get()->generators;
// generator-based environments must die in 1.0
bool genBasedEnv = false;
if (auto genDef = generators.find(environment)) {
genBasedEnv = true;
}
auto& contentControl = engine.getContentControl(); auto& contentControl = engine.getContentControl();
auto level = World::create( auto level = World::create(
name, name,
generatorID, genBasedEnv ? "" : environment,
genBasedEnv ? environment : "",
folder, folder,
seed, seed,
engine.getSettings(), engine.getSettings(),
*contentControl.get(), *contentControl.get(),
contentControl.getContentPacks() contentControl.getContentPacks()
); );
// generator-based environment initialization
if (genBasedEnv) {
level->environment.generator = environment;
}
if (!engine.isHeadless()) { if (!engine.isHeadless()) {
level->players->create(localPlayer); level->players->create(localPlayer);
} }

View file

@ -149,7 +149,7 @@ void LevelController::saveWorld() {
world->wfile->createDirectories(); world->wfile->createDirectories();
scripting::on_world_save(); scripting::on_world_save();
level->onSave(); level->onSave();
level->getWorld()->write(level.get()); level->getWorld()->write(*level);
} }
void LevelController::onWorldQuit() { void LevelController::onWorldQuit() {

View file

@ -125,7 +125,7 @@ static int l_is_night(lua::State* L) {
} }
static int l_get_generator(lua::State* L) { static int l_get_generator(lua::State* L) {
return lua::pushstring(L, require_world_info().generator); return lua::pushstring(L, require_level().environment.generator);
} }
static int l_get_chunk_data(lua::State* L) { static int l_get_chunk_data(lua::State* L) {

View file

@ -127,7 +127,7 @@ void Player::teleport(glm::vec3 position) {
void Player::attemptToChooseSpawnpoint() { void Player::attemptToChooseSpawnpoint() {
// looks bad to be here tbh // looks bad to be here tbh
const auto& generatorDef = const auto& generatorDef =
level.content.generators.require(level.getWorld()->getGenerator()); level.content.generators.require(level.environment.generator);
int minHeight = generatorDef.playerMinSpawnHeight; int minHeight = generatorDef.playerMinSpawnHeight;
int maxHeight = generatorDef.playerMaxSpawnHeight; int maxHeight = generatorDef.playerMaxSpawnHeight;

View file

@ -22,6 +22,7 @@ dv::value Environment::serialize() const {
{"clouds", sky.clouds}, {"clouds", sky.clouds},
{"sprites", std::move(skySpritesList)}, {"sprites", std::move(skySpritesList)},
})}, })},
{"generator", generator}
}); });
} }
@ -44,4 +45,5 @@ void Environment::deserialize(const dv::value& src) {
} }
} }
} }
src.at("generator").get(generator);
} }

View file

@ -56,6 +56,8 @@ public:
}; };
} sky; } sky;
std::string generator;
Environment() = default; Environment() = default;
dv::value serialize() const override; dv::value serialize() const override;

View file

@ -31,6 +31,7 @@ Level::Level(
entities(std::make_unique<Entities>(*this)), entities(std::make_unique<Entities>(*this)),
players(std::make_unique<Players>(*this)), players(std::make_unique<Players>(*this)),
pathfinding(std::make_unique<voxels::Pathfinding>(*this)) { pathfinding(std::make_unique<voxels::Pathfinding>(*this)) {
const auto& worldInfo = world->getInfo(); const auto& worldInfo = world->getInfo();
auto& cameraIndices = content.getIndices(ResourceType::CAMERA); auto& cameraIndices = content.getIndices(ResourceType::CAMERA);
for (size_t i = 0; i < cameraIndices.size(); i++) { for (size_t i = 0; i < cameraIndices.size(); i++) {

View file

@ -65,12 +65,12 @@ void World::writeResources(const Content& content) {
io::write_json(wfile->getResourcesFile(), root); io::write_json(wfile->getResourcesFile(), root);
} }
void World::write(Level* level) { void World::write(Level& level) {
level->chunks->saveAll(); level.chunks->saveAll();
info.nextEntityId = level->entities->peekNextID(); info.nextEntityId = level.entities->peekNextID();
wfile->write(this, &content); wfile->write(this, &content);
auto playerFile = level->players->serialize(); auto playerFile = level.players->serialize();
io::write_json(wfile->getPlayerFile(), playerFile); io::write_json(wfile->getPlayerFile(), playerFile);
writeResources(content); writeResources(content);
@ -78,7 +78,8 @@ void World::write(Level* level) {
std::unique_ptr<Level> World::create( std::unique_ptr<Level> World::create(
const std::string& name, const std::string& name,
const std::string& generator, const std::string& environment,
const std::string& generatorOverride,
const io::path& directory, const io::path& directory,
uint64_t seed, uint64_t seed,
EngineSettings& settings, EngineSettings& settings,
@ -87,7 +88,8 @@ std::unique_ptr<Level> World::create(
) { ) {
WorldInfo info {}; WorldInfo info {};
info.name = name; info.name = name;
info.generator = generator; info.environment = environment;
info.explicitGenerator = generatorOverride;
info.seed = seed; info.seed = seed;
auto world = std::make_unique<World>( auto world = std::make_unique<World>(
info, info,
@ -101,7 +103,7 @@ std::unique_ptr<Level> World::create(
logger.info() << "created world '" << name << "' (" logger.info() << "created world '" << name << "' ("
<< directory.string() << ")"; << directory.string() << ")";
} }
logger.info() << "world seed: " << seed << " generator: " << generator; logger.info() << "world seed: " << seed << " environment: " << environment;
return std::make_unique<Level>(std::move(world), content, settings); return std::make_unique<Level>(std::move(world), content, settings);
} }
@ -122,16 +124,19 @@ std::unique_ptr<Level> World::load(
<< worldFilesPtr->getFolder().string() << ")"; << worldFilesPtr->getFolder().string() << ")";
logger.info() << "world version: " << info->major << "." << info->minor logger.info() << "world version: " << info->major << "." << info->minor
<< " seed: " << info->seed << " seed: " << info->seed
<< " generator: " << info->generator; << " environment: " << info->environment;
auto world = std::make_unique<World>( auto worldPtr = std::make_unique<World>(
info.value(), std::move(worldFilesPtr), content, packs info.value(), std::move(worldFilesPtr), content, packs
); );
auto world = worldPtr.get();
auto& wfile = world->wfile; auto& wfile = world->wfile;
wfile->readResourcesData(content); wfile->readResourcesData(content);
auto level = std::make_unique<Level>(std::move(world), content, settings); auto level = std::make_unique<Level>(std::move(worldPtr), content, settings);
if (world->getEnvironment().empty()) {
level->environment.generator = world->getInfo().explicitGenerator;
}
io::path file = wfile->getPlayerFile(); io::path file = wfile->getPlayerFile();
if (!io::is_regular_file(file)) { if (!io::is_regular_file(file)) {
logger.warning() << "player.json does not exists"; logger.warning() << "player.json does not exists";
@ -163,8 +168,8 @@ void World::setName(const std::string& name) {
this->info.name = name; this->info.name = name;
} }
void World::setGenerator(const std::string& generator) { void World::setEnvironment(const std::string& environment) {
this->info.generator = generator; this->info.environment = environment;
} }
bool World::hasPack(const std::string& id) const { bool World::hasPack(const std::string& id) const {
@ -186,8 +191,8 @@ uint64_t World::getSeed() const {
return info.seed; return info.seed;
} }
std::string World::getGenerator() const { std::string World::getEnvironment() const {
return info.generator; return info.environment;
} }
const std::vector<ContentPack>& World::getPacks() const { const std::vector<ContentPack>& World::getPacks() const {
@ -196,7 +201,8 @@ const std::vector<ContentPack>& World::getPacks() const {
void WorldInfo::deserialize(const dv::value& root) { void WorldInfo::deserialize(const dv::value& root) {
name = root["name"].asString(); name = root["name"].asString();
generator = root["generator"].asString(generator); root.at("environment").get(environment);
root.at("generator").get(explicitGenerator);
seed = root["seed"].asInteger(seed); seed = root["seed"].asInteger(seed);
if (root.has("version")) { if (root.has("version")) {
@ -226,7 +232,11 @@ dv::value WorldInfo::serialize() const {
versionobj["minor"] = ENGINE_VERSION_MINOR; versionobj["minor"] = ENGINE_VERSION_MINOR;
root["name"] = name; root["name"] = name;
root["generator"] = generator; if (environment.empty()) {
root["generator"] = explicitGenerator;
} else {
root["environment"] = environment;
}
root["seed"] = seed; root["seed"] = seed;
auto& timeobj = root.object("time"); auto& timeobj = root.object("time");

View file

@ -23,7 +23,8 @@ public:
struct WorldInfo : public Serializable { struct WorldInfo : public Serializable {
std::string name; std::string name;
std::string generator; std::string environment;
std::string explicitGenerator;
uint64_t seed; uint64_t seed;
int64_t nextInventoryId = 1; int64_t nextInventoryId = 1;
int64_t nextPlayerId = 0; int64_t nextPlayerId = 0;
@ -76,7 +77,7 @@ public:
void updateTimers(float delta); void updateTimers(float delta);
/// @brief Write all unsaved level data to the world directory /// @brief Write all unsaved level data to the world directory
void write(Level* level); void write(Level& level);
/// @brief Check world indices and generate ContentReport if convert required /// @brief Check world indices and generate ContentReport if convert required
/// @param directory world directory /// @param directory world directory
@ -98,7 +99,8 @@ public:
/// @return Level instance containing World instance /// @return Level instance containing World instance
static std::unique_ptr<Level> create( static std::unique_ptr<Level> create(
const std::string& name, const std::string& name,
const std::string& generator, const std::string& environment,
const std::string& generatorOverride,
const io::path& directory, const io::path& directory,
uint64_t seed, uint64_t seed,
EngineSettings& settings, EngineSettings& settings,
@ -123,7 +125,7 @@ public:
void setName(const std::string& name); void setName(const std::string& name);
void setSeed(uint64_t seed); void setSeed(uint64_t seed);
void setGenerator(const std::string& generator); void setEnvironment(const std::string& environment);
/// @brief Check if world has content-pack installed /// @brief Check if world has content-pack installed
/// @param id content-pack id /// @param id content-pack id
@ -137,7 +139,7 @@ public:
uint64_t getSeed() const; uint64_t getSeed() const;
/// @brief Get world generator id /// @brief Get world generator id
std::string getGenerator() const; std::string getEnvironment() const;
bool isNameless() const { bool isNameless() const {
return info.name.empty(); return info.name.empty();