Skip to content

Commit

Permalink
CustomSystem: support loading Json partial systems
Browse files Browse the repository at this point in the history
- Migration path for old 02_local_stars.lua
- CustomSystem definitions use nicer storage values for sector position
- Loads full system definitions from systems/custom
- Loads partial system definitions from systems/partial
- Add example Json-based partial system def
  • Loading branch information
sturnclaw committed Sep 15, 2023
1 parent 2e3e958 commit 1423709
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 35 deletions.
2 changes: 1 addition & 1 deletion data/systems/02_local_stars.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

CustomSystem:new('GJ 1075',{'STAR_K'}):add_to_sector(2,-1,-4,v(0.451,0.409,0.034))
-- CustomSystem:new('GJ 1075',{'STAR_K'}):add_to_sector(2,-1,-4,v(0.451,0.409,0.034))
CustomSystem:new('NN 3707',{'STAR_M'}):add_to_sector(-1,3,-1,v(0.845,0.512,0.054))
CustomSystem:new('NN 3253',{'STAR_M'}):add_to_sector(3,-2,1,v(0.185,0.023,0.148))
CustomSystem:new('Gliese 766',{'STAR_M','STAR_M'}):add_to_sector(-4,-2,1,v(0.511,0.265,0.998))
Expand Down
3 changes: 3 additions & 0 deletions data/systems/partial/02_local_stars.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
{"name":"GJ 1075","stars":["STAR_K"],"sector":[2,-1,-4],"pos":[3.608,3.272,0.272]}
]
96 changes: 69 additions & 27 deletions src/galaxy/CustomSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,16 +642,21 @@ void CustomSystem::LoadFromJson(const Json &systemdef)
primaryType[starIdx++] = SystemBody::BodyType(EnumStrings::GetValue("BodyType", type.get<std::string>().c_str()));
}

sectorX = systemdef["sectorX"];
sectorY = systemdef["sectorY"];
sectorZ = systemdef["sectorZ"];
const Json &sector = systemdef["sector"];
sectorX = sector[0].get<int32_t>();
sectorZ = sector[1].get<int32_t>();
sectorY = sector[2].get<int32_t>();

pos = systemdef["pos"];
seed = systemdef["seed"];
const Json &position = systemdef["pos"];
pos.x = sector[0].get<float>();
pos.y = sector[1].get<float>();
pos.z = sector[2].get<float>();

seed = systemdef.value<uint32_t>("seed", 0);
explored = systemdef.value<bool>("explored", true);
lawlessness = systemdef.value<fixed>("lawlessness", 0);

want_rand_seed = false;
want_rand_seed = !systemdef.count("seed");
want_rand_explored = !systemdef.count("explored");
want_rand_lawlessness = !systemdef.count("lawlessness");

Expand All @@ -678,11 +683,8 @@ void CustomSystem::SaveToJson(Json &obj)

obj["numStars"] = numStars;

obj["sectorX"] = sectorX;
obj["sectorY"] = sectorY;
obj["sectorZ"] = sectorZ;

obj["pos"] = pos;
obj["sector"] = Json::array({ sectorX, sectorY, sectorZ });
obj["pos"] = Json::array({ pos.x, pos.y, pos.z });
obj["seed"] = seed;

if (!want_rand_explored)
Expand Down Expand Up @@ -760,18 +762,37 @@ void CustomSystemsDatabase::Load()

LoadAllLuaSystems();

auto enumerator = FileSystem::FileEnumerator(FileSystem::gameDataFiles, m_customSysDirectory, FileSystem::FileEnumerator::Recurse);
for (auto &file : enumerator) {
// Load Json array files containing random-fill system definitions
std::string partialPath = FileSystem::JoinPathBelow(m_customSysDirectory, "partial");
for (auto &file : FileSystem::gameDataFiles.Recurse(partialPath)) {
if (!ends_with_ci(file.GetPath(), ".json"))
continue;

PROFILE_SCOPED_DESC("Load Custom System File")

PROFILE_SCOPED_DESC("Load Partial System List")
const Json fileData = JsonUtils::LoadJsonDataFile(file.GetPath());
CustomSystem *sys = LoadSystemFromJSON(file.GetPath(), fileData);
for (const Json &sysdef : fileData) {
if (!sysdef.is_object())
continue;

SystemPath path(sys->sectorX, sys->sectorY, sys->sectorZ);
AddCustomSystem(path, sys);
LoadSystemFromJSON(file.GetPath(), sysdef);
}
}

// Load top-level custom system defines
for (auto &file : FileSystem::gameDataFiles.Enumerate(m_customSysDirectory, 0)) {
if (!ends_with_ci(file.GetPath(), ".json"))
continue;

LoadSystemFromJSON(file.GetPath(), JsonUtils::LoadJsonDataFile(file.GetPath()));
}

// Load all complete custom system definitions
std::string customPath = FileSystem::JoinPathBelow(m_customSysDirectory, "custom");
for (auto &file : FileSystem::gameDataFiles.Recurse(customPath)) {
if (!ends_with_ci(file.GetPath(), ".json"))
continue;

LoadSystemFromJSON(file.GetPath(), JsonUtils::LoadJsonDataFile(file.GetPath()));
}
}

Expand Down Expand Up @@ -813,7 +834,7 @@ const CustomSystem *CustomSystemsDatabase::LoadSystem(std::string_view filepath)
return m_sectorMap[m_lastAddedSystem.first][m_lastAddedSystem.second];
}

CustomSystem *CustomSystemsDatabase::LoadSystemFromJSON(std::string_view filename, const Json &systemdef)
CustomSystem *CustomSystemsDatabase::LoadSystemFromJSON(std::string_view filename, const Json &systemdef, bool mergeWithGalaxy)
{
PROFILE_SCOPED()

Expand All @@ -826,8 +847,8 @@ CustomSystem *CustomSystemsDatabase::LoadSystemFromJSON(std::string_view filenam
// Validate number of stars
constexpr int MAX_STARS = COUNTOF(sys->primaryType);
if (sys->numStars > MAX_STARS) {
Log::Warning("Custom system {} defines {} stars of {} max! Extra stars will not be used in Sector generation.",
filename, sys->numStars, MAX_STARS);
Log::Warning("Custom system {} ({}) defines {} stars of {} max! Extra stars will not be used in Sector generation.",
sys->name, filename, sys->numStars, MAX_STARS);
sys->numStars = MAX_STARS;
}

Expand All @@ -839,12 +860,30 @@ CustomSystem *CustomSystemsDatabase::LoadSystemFromJSON(std::string_view filenam
} else {
sys->faction = GetGalaxy()->GetFactions()->GetFaction(factionName);
if (sys->faction->idx == Faction::BAD_FACTION_IDX) {
Log::Warning("Unknown faction {} for custom system {}.", factionName, filename);
Log::Warning("Unknown faction {} for custom system {} ({}).", factionName, sys->name, filename);
sys->faction = nullptr;
}
}
}

if (sys->want_rand_seed) {
Random rand = {
hash_32_fnv1a(sys->name.data(), sys->name.size()),
uint32_t(sys->sectorX), uint32_t(sys->sectorY), uint32_t(sys->sectorZ), UNIVERSE_SEED
};

sys->seed = rand.Int32();
sys->want_rand_seed = false;
}

// Partially-defined system, return as-is
if (!systemdef.count("bodies")) {
if (mergeWithGalaxy)
AddCustomSystem(SystemPath(sys->sectorX, sys->sectorY, sys->sectorZ), sys);

return sys;
}

size_t numBodies = systemdef["bodies"].size();
sys->bodies.reserve(numBodies);

Expand All @@ -860,8 +899,8 @@ CustomSystem *CustomSystemsDatabase::LoadSystemFromJSON(std::string_view filenam

for (const Json &childIndex : bodynode["children"]) {
if (childIndex >= numBodies) {
Log::Warning("Body {} in system {} has out-of-range child index {}",
body->bodyData.m_name, filename, childIndex.get<uint32_t>());
Log::Warning("Body {} in system {} ({}) has out-of-range child index {}",
body->bodyData.m_name, sys->name, filename, childIndex.get<uint32_t>());
continue;
}

Expand All @@ -883,6 +922,9 @@ CustomSystem *CustomSystemsDatabase::LoadSystemFromJSON(std::string_view filenam

}

if (mergeWithGalaxy)
AddCustomSystem(SystemPath(sys->sectorX, sys->sectorY, sys->sectorZ), sys);

return sys;

} catch (Json::out_of_range &e) {
Expand Down Expand Up @@ -923,14 +965,14 @@ void CustomSystemsDatabase::AddCustomSystem(const SystemPath &path, CustomSystem
if (system->name != csys->name)
continue;

// Partially-defined systems are ignored if there is a fully-defined
// system with the same name
// Partially-defined systems are ignored if there is an existing
// system already loaded with that name in that sector
if (csys->IsRandom()) {
delete csys;
return;
}

// Fully-defined custom systems override partially-defined systems
// Fully-defined custom systems override existing systems
csys->systemIndex = system->systemIndex;
m_lastAddedSystem = SystemIndex(path, csys->systemIndex);

Expand Down
2 changes: 1 addition & 1 deletion src/galaxy/CustomSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class CustomSystemsDatabase {
void LoadAllLuaSystems();
const CustomSystem *LoadSystem(std::string_view filepath);

CustomSystem *LoadSystemFromJSON(std::string_view filename, const Json &systemdef);
CustomSystem *LoadSystemFromJSON(std::string_view filename, const Json &systemdef, bool mergeWithGalaxy = true);

typedef std::vector<const CustomSystem *> SystemList;
// XXX this is not as const-safe as it should be
Expand Down
6 changes: 4 additions & 2 deletions src/galaxy/Factions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ static void RegisterFactionsAPI(lua_State *L)

void FactionsDatabase::Init()
{
PROFILE_SCOPED()

assert(!s_activeFactionsDatabase);
s_activeFactionsDatabase = this;

Expand Down Expand Up @@ -491,6 +493,8 @@ void FactionsDatabase::Init()

void FactionsDatabase::PostInit()
{
PROFILE_SCOPED()

assert(m_initialized);
assert(m_galaxy->IsInitialized());
SetHomeSectors();
Expand Down Expand Up @@ -792,7 +796,6 @@ Faction::Faction(Galaxy *galaxy) :

void FactionsDatabase::Octsapling::Add(const Faction *faction)
{
PROFILE_SCOPED()
/* The general principle here is to put the faction in every octbox cell that a system
that is a member of that faction could be in. This should let us cut the number
of factions that have to be checked by GetNearestFaction, by eliminating right off
Expand Down Expand Up @@ -874,7 +877,6 @@ void FactionsDatabase::Octsapling::PruneDuplicates(const int bx, const int by, c

const std::vector<const Faction *> &FactionsDatabase::Octsapling::CandidateFactions(const Sector::System *sys) const
{
PROFILE_SCOPED()
/* answer the factions that we've put in the same octobox cell as the one the
system would go in. This part happens every time we do GetNearest faction
so *is* performance criticale.e
Expand Down
6 changes: 2 additions & 4 deletions src/galaxy/StarSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,10 +573,8 @@ void StarSystem::DumpToJson(Json &obj)
for (size_t idx = 0; idx < m_numStars; idx++)
out_types.push_back(EnumStrings::GetString("BodyType", m_stars[idx]->GetType()));

obj["sectorX"] = m_path.sectorX;
obj["sectorY"] = m_path.sectorY;
obj["sectorZ"] = m_path.sectorZ;
obj["pos"] = m_pos;
obj["sector"] = Json::array({ m_path.sectorX, m_path.sectorY, m_path.sectorZ });
obj["pos"] = Json::array({ m_pos.x, m_pos.y, m_pos.z });

obj["seed"] = m_seed;
obj["explored"] = m_explored == ExplorationState::eEXPLORED_AT_START;
Expand Down

0 comments on commit 1423709

Please sign in to comment.