Infinity Engine v0.6.20
C++ API Documentation
Loading...
Searching...
No Matches
Using the InfinityEngine API

The InfinityEngine class is your primary interface for loading cores, discovering systems, and managing procedural generation workflows. This tutorial covers the essential patterns for working with the engine API effectively.

Engine Initialization and Core Loading

Basic Engine Creation

#include <Infinity/InfinityInit.h>
#include <Infinity/Engine/InfinityEngine.h>
// Always initialize first
// Create an empty engine
// Or load a core immediately
Infinity::Engine::InfinityEngine engine("path/to/project.infinitycore");
Main entry point to the InfinityEngine API for procedural generation.
Definition InfinityEngine.hpp:26
INFINITY_API_PUBLIC void InfinityInit(void)
Initializes the Infinity Engine.

Loading Multiple Cores

The InfinityEngine can work with one core at a time. To switch between cores, create new engine instances:

void processMultipleCores() {
std::vector<std::string> coreFiles = {
"terrain/terrain_generation.infinitycore",
"buildings/building_system.infinitycore",
"vegetation/forest_generator.infinitycore"
};
std::vector<Infinity::Engine::InfinityEngine> engines;
for (const auto& coreFile : coreFiles) {
try {
engines.emplace_back(Infinity::Engine::InfinityEngine(coreFile));
}
catch (const std::exception& e) {
std::cerr << "Failed to load " << coreFile << ": " << e.what() << std::endl;
}
}
}

Discovering and Accessing Systems

Listing Available Systems

void exploreCoreSystems(const Infinity::Engine::InfinityEngine& engine) {
// Get all root-level systems
auto rootSystems = engine.rootSystems();
std::cout << "Root systems (" << rootSystems.size() << "):" << std::endl;
for (const auto& system : rootSystems) {
std::cout << " - " << system->id() << std::endl;
}
// Get ALL systems (including nested/child systems)
// NOTE: This functionality is currently in-development, and only returns root systems at this time.
auto allSystems = engine.allSystems();
std::cout << "\\nAll systems (" << allSystems.size() << "):" << std::endl;
for (const auto& system : allSystems) {
std::cout << " - " << system->id() << std::endl;
}
}
std::vector< std::shared_ptr< Infinity::Procedural::ProceduralSystem > > rootSystems() const
Retrieves all root-level ProceduralSystems in the loaded core.
std::vector< std::shared_ptr< Infinity::Procedural::ProceduralSystem > > allSystems() const
Retrieves all ProceduralSystems in the loaded core.

Accessing Specific Systems

void workWithSpecificSystem(const Infinity::Engine::InfinityEngine& engine) {
// Access by exact path/ID
auto terrainSystem = engine.system("TerrainGenerator");
if (terrainSystem) {
std::cout << "Found terrain system: " << terrainSystem->id() << std::endl;
}
// Handle nested systems (if applicable)
auto nestedSystem = engine.system("WorldGen/TerrainDetail/ErosionSimulation");
if (nestedSystem) {
std::cout << "Found nested system: " << nestedSystem->id() << std::endl;
}
// Search for systems by pattern
// NOTE: This functionality is currently in-development, and only returns root systems at this time.
auto allSystems = engine.allSystems();
for (const auto& system : allSystems) {
if (system->id().find("Terrain") != std::string::npos) {
std::cout << "Terrain-related system: " << system->id() << std::endl;
}
}
}
std::shared_ptr< Infinity::Procedural::ProceduralSystem > system(const std::string &path) const
Retrieves a specific ProceduralSystem by its path identifier.

Error Handling and Validation

Robust Core Loading

std::unique_ptr<Infinity::Engine::InfinityEngine> loadCoreRobustly(
const std::filesystem::path& corePath) {
// Validate file existence
if (!std::filesystem::exists(corePath)) {
throw std::runtime_error("Core file not found: " + corePath.string());
}
// Check file extension
if (corePath.extension() != ".infinitycore") {
std::cerr << "Warning: Unexpected file extension for core: "
<< corePath.extension().string() << std::endl;
}
try {
auto engine = std::make_unique<Infinity::Engine::InfinityEngine>(corePath);
// Validate core contents
auto systems = engine->allSystems();
if (systems.empty()) {
std::cerr << "Warning: Core contains no systems" << std::endl;
}
std::cout << "Successfully loaded core with " << systems.size() << " systems" << std::endl;
return engine;
}
catch (const std::exception& e) {
throw std::runtime_error("Failed to load core: " + std::string(e.what()));
}
}

System Access Validation

bool validateSystemAccess(const Infinity::Engine::InfinityEngine& engine,
const std::string& systemName) {
auto system = engine.system(systemName);
if (!system) {
std::cerr << "System not found: " << systemName << std::endl;
// Suggest similar systems
auto allSystems = engine.allSystems();
std::cout << "Available systems:" << std::endl;
for (const auto& available : allSystems) {
std::cout << " - " << available->id() << std::endl;
}
return false;
}
std::cout << "System found: " << system->id() << std::endl;
return true;
}

Advanced Usage Patterns

Executing Multiple Systems in Sequence

void sequentialSystemExecution(const Infinity::Engine::InfinityEngine& engine) {
std::vector<std::string> processingOrder = {
"TerrainBase",
"TerrainDetail",
"VegetationPlacement",
"FinalComposition"
};
// Shared data context for systems that need to pass results
struct ProcessingContext {
uint64_t seed = 12345;
float worldScale = 1000.0f;
// Add shared parameters as needed
} context;
for (const auto& systemName : processingOrder) {
auto system = engine.system(systemName);
if (!system) {
std::cerr << "Skipping missing system: " << systemName << std::endl;
continue;
}
std::cout << "Processing: " << systemName << std::endl;
// Configure system with shared context
system->setSeed(context.seed);
system->setIn("worldScale", context.worldScale);
// Execute system
system->execute();
// Could extract results and pass to next system if needed
std::cout << "Completed: " << systemName << std::endl;
}
}

Parallel System Execution (Independent Systems)

#include <future>
#include <thread>
void parallelSystemExecution(const Infinity::Engine::InfinityEngine& engine) {
// Systems that can run independently
std::vector<std::string> independentSystems = {
"TreeGenerator",
"RockScatter",
"WaterGeneration",
"CloudSystem"
};
std::vector<std::future<void>> futures;
for (const auto& systemName : independentSystems) {
auto system = engine.system(systemName);
if (!system) continue;
// Launch async execution
futures.emplace_back(std::async(std::launch::async, [system, systemName]() {
try {
std::cout << "Starting: " << systemName << std::endl;
system->setSeed(std::hash<std::string>{}(systemName)); // Unique seed per system
system->execute();
std::cout << "Completed: " << systemName << std::endl;
}
catch (const std::exception& e) {
std::cerr << "Error in " << systemName << ": " << e.what() << std::endl;
}
}));
}
// Wait for all systems to complete
for (auto& future : futures) {
future.wait();
}
std::cout << "All independent systems completed" << std::endl;
}

Dynamic System Selection

void dynamicSystemSelection(const Infinity::Engine::InfinityEngine& engine) {
auto allSystems = engine.allSystems();
// Runtime selection based on criteria
auto selectSystemByPrefix = [&](const std::string& prefix) ->
std::shared_ptr<Infinity::Procedural::ProceduralSystem> {
for (const auto& system : allSystems) {
if (system->id().starts_with(prefix)) {
return system;
}
}
return nullptr;
};
// Select different systems based on runtime conditions
std::string terrainType = "Mountain"; // Could come from user input or config
if (auto system = selectSystemByPrefix(terrainType)) {
std::cout << "Using terrain system: " << system->id() << std::endl;
system->execute();
} else {
std::cout << "No system found for terrain type: " << terrainType << std::endl;
// Fallback to default
if (auto defaultSystem = engine.system("DefaultTerrain")) {
std::cout << "Using default terrain system" << std::endl;
defaultSystem->execute();
}
}
}

Integration Patterns

Engine Wrapper Class

For larger applications, consider wrapping the engine in a higher-level interface:

class ProceduralGenerationManager {
private:
std::unique_ptr<Infinity::Engine::InfinityEngine> engine_;
std::filesystem::path currentCorePath_;
public:
bool loadCore(const std::filesystem::path& corePath) {
try {
engine_ = std::make_unique<Infinity::Engine::InfinityEngine>(corePath);
currentCorePath_ = corePath;
return true;
}
catch (const std::exception& e) {
std::cerr << "Failed to load core: " << e.what() << std::endl;
return false;
}
}
std::vector<std::string> getAvailableSystemNames() const {
if (!engine_) return {};
auto systems = engine_->allSystems();
std::vector<std::string> names;
names.reserve(systems.size());
for (const auto& system : systems) {
names.push_back(system->id());
}
return names;
}
bool executeSystem(const std::string& systemName, uint64_t seed = 0) {
if (!engine_) return false;
auto system = engine_->system(systemName);
if (!system) return false;
try {
if (seed != 0) {
system->setSeed(seed);
}
system->execute();
return true;
}
catch (const std::exception& e) {
std::cerr << "System execution failed: " << e.what() << std::endl;
return false;
}
}
std::shared_ptr<Infinity::Procedural::ProceduralSystem> getSystem(const std::string& name) const {
return engine_ ? engine_->system(name) : nullptr;
}
};

Best Practices

  1. Always call InfinityInit() before creating any engine instances
  2. Handle exceptions when loading cores or accessing systems
  3. Validate system existence before attempting operations
  4. Use descriptive system names in your cores for easier access
  5. Consider system dependencies when executing multiple systems
  6. Cache system references if you'll be using them repeatedly
  7. Use appropriate error logging to debug core loading issues

Troubleshooting

Engine creation fails:

  • Ensure InfinityInit() was called first
  • Verify core file path and accessibility
  • Check that all required component libraries are available

System not found:

  • List all systems to verify exact naming
  • Check for case sensitivity in system names
  • Ensure the system wasn't filtered out during core loading

Performance issues:

  • Avoid creating multiple engine instances unnecessarily
  • Cache system references for repeated use
  • Consider async execution for independent systems

Next Steps

Now that you understand the InfinityEngine API: