add headless mode (engine initialization and finalization)
This commit is contained in:
parent
1ab3707343
commit
ee1a170376
@ -8,6 +8,9 @@
|
|||||||
#include "coders/wav.hpp"
|
#include "coders/wav.hpp"
|
||||||
#include "AL/ALAudio.hpp"
|
#include "AL/ALAudio.hpp"
|
||||||
#include "NoAudio.hpp"
|
#include "NoAudio.hpp"
|
||||||
|
#include "debug/Logger.hpp"
|
||||||
|
|
||||||
|
static debug::Logger logger("audio");
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
static speakerid_t nextId = 1;
|
static speakerid_t nextId = 1;
|
||||||
@ -147,10 +150,14 @@ public:
|
|||||||
|
|
||||||
void audio::initialize(bool enabled) {
|
void audio::initialize(bool enabled) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
logger.info() << "initializing ALAudio backend";
|
||||||
backend = ALAudio::create().release();
|
backend = ALAudio::create().release();
|
||||||
}
|
}
|
||||||
if (backend == nullptr) {
|
if (backend == nullptr) {
|
||||||
|
if (enabled) {
|
||||||
std::cerr << "could not to initialize audio" << std::endl;
|
std::cerr << "could not to initialize audio" << std::endl;
|
||||||
|
}
|
||||||
|
logger.info() << "initializing NoAudio backend";
|
||||||
backend = NoAudio::create().release();
|
backend = NoAudio::create().release();
|
||||||
}
|
}
|
||||||
create_channel("master");
|
create_channel("master");
|
||||||
|
|||||||
@ -69,18 +69,25 @@ static std::unique_ptr<ImageData> load_icon(const fs::path& resdir) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::Engine(EnginePaths& paths)
|
Engine::Engine(CoreParameters coreParameters)
|
||||||
: settings(), settingsHandler({settings}), paths(paths),
|
: params(std::move(coreParameters)),
|
||||||
|
settings(),
|
||||||
|
settingsHandler({settings}),
|
||||||
interpreter(std::make_unique<cmd::CommandsInterpreter>()),
|
interpreter(std::make_unique<cmd::CommandsInterpreter>()),
|
||||||
network(network::Network::create(settings.network))
|
network(network::Network::create(settings.network)) {
|
||||||
{
|
if (params.headless) {
|
||||||
|
logger.info() << "headless mode is enabled";
|
||||||
|
}
|
||||||
|
paths.setResourcesFolder(params.resFolder);
|
||||||
|
paths.setUserFilesFolder(params.userFolder);
|
||||||
paths.prepare();
|
paths.prepare();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
auto resdir = paths.getResourcesFolder();
|
auto resdir = paths.getResourcesFolder();
|
||||||
|
|
||||||
controller = std::make_unique<EngineController>(this);
|
controller = std::make_unique<EngineController>(this);
|
||||||
if (Window::initialize(&this->settings.display)){
|
if (!params.headless) {
|
||||||
|
if (Window::initialize(&settings.display)){
|
||||||
throw initialize_error("could not initialize window");
|
throw initialize_error("could not initialize window");
|
||||||
}
|
}
|
||||||
if (auto icon = load_icon(resdir)) {
|
if (auto icon = load_icon(resdir)) {
|
||||||
@ -88,23 +95,25 @@ Engine::Engine(EnginePaths& paths)
|
|||||||
Window::setIcon(icon.get());
|
Window::setIcon(icon.get());
|
||||||
}
|
}
|
||||||
loadControls();
|
loadControls();
|
||||||
audio::initialize(settings.audio.enabled.get());
|
|
||||||
|
gui = std::make_unique<gui::GUI>();
|
||||||
|
if (ENGINE_DEBUG_BUILD) {
|
||||||
|
menus::create_version_label(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
audio::initialize(settings.audio.enabled.get() && !params.headless);
|
||||||
create_channel(this, "master", settings.audio.volumeMaster);
|
create_channel(this, "master", settings.audio.volumeMaster);
|
||||||
create_channel(this, "regular", settings.audio.volumeRegular);
|
create_channel(this, "regular", settings.audio.volumeRegular);
|
||||||
create_channel(this, "music", settings.audio.volumeMusic);
|
create_channel(this, "music", settings.audio.volumeMusic);
|
||||||
create_channel(this, "ambient", settings.audio.volumeAmbient);
|
create_channel(this, "ambient", settings.audio.volumeAmbient);
|
||||||
create_channel(this, "ui", settings.audio.volumeUI);
|
create_channel(this, "ui", settings.audio.volumeUI);
|
||||||
|
|
||||||
gui = std::make_unique<gui::GUI>();
|
|
||||||
if (settings.ui.language.get() == "auto") {
|
if (settings.ui.language.get() == "auto") {
|
||||||
settings.ui.language.set(langs::locale_by_envlocale(
|
settings.ui.language.set(langs::locale_by_envlocale(
|
||||||
platform::detect_locale(),
|
platform::detect_locale(),
|
||||||
paths.getResourcesFolder()
|
paths.getResourcesFolder()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (ENGINE_DEBUG_BUILD) {
|
|
||||||
menus::create_version_label(this);
|
|
||||||
}
|
|
||||||
keepAlive(settings.ui.language.observe([=](auto lang) {
|
keepAlive(settings.ui.language.observe([=](auto lang) {
|
||||||
setLanguage(lang);
|
setLanguage(lang);
|
||||||
}, true));
|
}, true));
|
||||||
@ -165,6 +174,14 @@ void Engine::saveScreenshot() {
|
|||||||
logger.info() << "saved screenshot as " << filename.u8string();
|
logger.info() << "saved screenshot as " << filename.u8string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::run() {
|
||||||
|
if (params.headless) {
|
||||||
|
logger.info() << "nothing to do";
|
||||||
|
} else {
|
||||||
|
mainloop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::mainloop() {
|
void Engine::mainloop() {
|
||||||
logger.info() << "starting menu screen";
|
logger.info() << "starting menu screen";
|
||||||
setScreen(std::make_shared<MenuScreen>(this));
|
setScreen(std::make_shared<MenuScreen>(this));
|
||||||
@ -219,9 +236,11 @@ void Engine::processPostRunnables() {
|
|||||||
void Engine::saveSettings() {
|
void Engine::saveSettings() {
|
||||||
logger.info() << "saving settings";
|
logger.info() << "saving settings";
|
||||||
files::write_string(paths.getSettingsFile(), toml::stringify(settingsHandler));
|
files::write_string(paths.getSettingsFile(), toml::stringify(settingsHandler));
|
||||||
|
if (!params.headless) {
|
||||||
logger.info() << "saving bindings";
|
logger.info() << "saving bindings";
|
||||||
files::write_string(paths.getControlsFile(), Events::writeBindings());
|
files::write_string(paths.getControlsFile(), Events::writeBindings());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Engine::~Engine() {
|
Engine::~Engine() {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
@ -233,13 +252,18 @@ Engine::~Engine() {
|
|||||||
content.reset();
|
content.reset();
|
||||||
assets.reset();
|
assets.reset();
|
||||||
interpreter.reset();
|
interpreter.reset();
|
||||||
|
if (gui) {
|
||||||
gui.reset();
|
gui.reset();
|
||||||
logger.info() << "gui finished";
|
logger.info() << "gui finished";
|
||||||
|
}
|
||||||
audio::close();
|
audio::close();
|
||||||
network.reset();
|
network.reset();
|
||||||
scripting::close();
|
scripting::close();
|
||||||
logger.info() << "scripting finished";
|
logger.info() << "scripting finished";
|
||||||
|
if (!params.headless) {
|
||||||
Window::terminate();
|
Window::terminate();
|
||||||
|
logger.info() << "window closed";
|
||||||
|
}
|
||||||
logger.info() << "engine finished";
|
logger.info() << "engine finished";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,8 +458,10 @@ void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
|||||||
|
|
||||||
void Engine::setLanguage(std::string locale) {
|
void Engine::setLanguage(std::string locale) {
|
||||||
langs::setup(paths.getResourcesFolder(), std::move(locale), contentPacks);
|
langs::setup(paths.getResourcesFolder(), std::move(locale), contentPacks);
|
||||||
|
if (gui) {
|
||||||
gui->getMenu()->setPageLoader(menus::create_page_loader(this));
|
gui->getMenu()->setPageLoader(menus::create_page_loader(this));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gui::GUI* Engine::getGUI() {
|
gui::GUI* Engine::getGUI() {
|
||||||
return gui.get();
|
return gui.get();
|
||||||
|
|||||||
@ -45,10 +45,17 @@ public:
|
|||||||
initialize_error(const std::string& message) : std::runtime_error(message) {}
|
initialize_error(const std::string& message) : std::runtime_error(message) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CoreParameters {
|
||||||
|
bool headless = false;
|
||||||
|
std::filesystem::path resFolder {"res"};
|
||||||
|
std::filesystem::path userFolder {"."};
|
||||||
|
};
|
||||||
|
|
||||||
class Engine : public util::ObjectsKeeper {
|
class Engine : public util::ObjectsKeeper {
|
||||||
|
CoreParameters params;
|
||||||
EngineSettings settings;
|
EngineSettings settings;
|
||||||
SettingsHandler settingsHandler;
|
SettingsHandler settingsHandler;
|
||||||
EnginePaths& paths;
|
EnginePaths paths;
|
||||||
|
|
||||||
std::unique_ptr<Assets> assets;
|
std::unique_ptr<Assets> assets;
|
||||||
std::shared_ptr<Screen> screen;
|
std::shared_ptr<Screen> screen;
|
||||||
@ -77,9 +84,12 @@ class Engine : public util::ObjectsKeeper {
|
|||||||
void processPostRunnables();
|
void processPostRunnables();
|
||||||
void loadAssets();
|
void loadAssets();
|
||||||
public:
|
public:
|
||||||
Engine(EnginePaths& paths);
|
Engine(CoreParameters coreParameters);
|
||||||
~Engine();
|
~Engine();
|
||||||
|
|
||||||
|
/// @brief Start the engine
|
||||||
|
void run();
|
||||||
|
|
||||||
/// @brief Start main engine input/update/render loop.
|
/// @brief Start main engine input/update/render loop.
|
||||||
/// Automatically sets MenuScreen
|
/// Automatically sets MenuScreen
|
||||||
void mainloop();
|
void mainloop();
|
||||||
|
|||||||
@ -48,6 +48,17 @@ static std::filesystem::path toCanonic(std::filesystem::path path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EnginePaths::prepare() {
|
void EnginePaths::prepare() {
|
||||||
|
logger.info() << "resources folder: " << fs::canonical(resourcesFolder).u8string();
|
||||||
|
logger.info() << "user files folder: " << fs::canonical(userFilesFolder).u8string();
|
||||||
|
|
||||||
|
if (!fs::is_directory(resourcesFolder)) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
resourcesFolder.u8string() + " is not a directory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!fs::is_directory(userFilesFolder)) {
|
||||||
|
fs::create_directories(userFilesFolder);
|
||||||
|
}
|
||||||
auto contentFolder = userFilesFolder / CONTENT_FOLDER;
|
auto contentFolder = userFilesFolder / CONTENT_FOLDER;
|
||||||
if (!fs::is_directory(contentFolder)) {
|
if (!fs::is_directory(contentFolder)) {
|
||||||
fs::create_directories(contentFolder);
|
fs::create_directories(contentFolder);
|
||||||
|
|||||||
12
src/main.cpp
12
src/main.cpp
@ -1,5 +1,4 @@
|
|||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "files/engine_paths.hpp"
|
|
||||||
#include "util/platform.hpp"
|
#include "util/platform.hpp"
|
||||||
#include "util/command_line.hpp"
|
#include "util/command_line.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
@ -11,15 +10,14 @@ static debug::Logger logger("main");
|
|||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
debug::Logger::init("latest.log");
|
debug::Logger::init("latest.log");
|
||||||
|
|
||||||
EnginePaths paths;
|
CoreParameters coreParameters;
|
||||||
if (!parse_cmdline(argc, argv, paths))
|
if (!parse_cmdline(argc, argv, coreParameters)) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
platform::configure_encoding();
|
platform::configure_encoding();
|
||||||
try {
|
try {
|
||||||
Engine(paths).mainloop();
|
Engine(std::move(coreParameters)).run();
|
||||||
}
|
} catch (const initialize_error& err) {
|
||||||
catch (const initialize_error& err) {
|
|
||||||
logger.error() << "could not to initialize engine\n" << err.what();
|
logger.error() << "could not to initialize engine\n" << err.what();
|
||||||
}
|
}
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "files/engine_paths.hpp"
|
#include "files/engine_paths.hpp"
|
||||||
|
#include "engine.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
@ -41,27 +42,24 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static bool perform_keyword(
|
static bool perform_keyword(
|
||||||
ArgsReader& reader, const std::string& keyword, EnginePaths& paths
|
ArgsReader& reader, const std::string& keyword, CoreParameters& params
|
||||||
) {
|
) {
|
||||||
if (keyword == "--res") {
|
if (keyword == "--res") {
|
||||||
auto token = reader.next();
|
auto token = reader.next();
|
||||||
if (!fs::is_directory(fs::path(token))) {
|
params.resFolder = fs::u8path(token);
|
||||||
throw std::runtime_error(token + " is not a directory");
|
|
||||||
}
|
|
||||||
paths.setResourcesFolder(fs::path(token));
|
|
||||||
std::cout << "resources folder: " << token << std::endl;
|
|
||||||
} else if (keyword == "--dir") {
|
} else if (keyword == "--dir") {
|
||||||
auto token = reader.next();
|
auto token = reader.next();
|
||||||
if (!fs::is_directory(fs::path(token))) {
|
params.userFolder = fs::u8path(token);
|
||||||
fs::create_directories(fs::path(token));
|
|
||||||
}
|
|
||||||
paths.setUserFilesFolder(fs::path(token));
|
|
||||||
std::cout << "userfiles folder: " << token << std::endl;
|
|
||||||
} else if (keyword == "--help" || keyword == "-h") {
|
} else if (keyword == "--help" || keyword == "-h") {
|
||||||
std::cout << "VoxelEngine command-line arguments:" << std::endl;
|
std::cout << "VoxelEngine command-line arguments:\n";
|
||||||
std::cout << " --res [path] - set resources directory" << std::endl;
|
std::cout << " --help - show help\n";
|
||||||
std::cout << " --dir [path] - set userfiles directory" << std::endl;
|
std::cout << " --res [path] - set resources directory\n";
|
||||||
|
std::cout << " --dir [path] - set userfiles directory\n";
|
||||||
|
std::cout << " --headless - run in headless mode\n";
|
||||||
|
std::cout << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
} else if (keyword == "--headless") {
|
||||||
|
params.headless = true;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "unknown argument " << keyword << std::endl;
|
std::cerr << "unknown argument " << keyword << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -69,13 +67,13 @@ static bool perform_keyword(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_cmdline(int argc, char** argv, EnginePaths& paths) {
|
bool parse_cmdline(int argc, char** argv, CoreParameters& params) {
|
||||||
ArgsReader reader(argc, argv);
|
ArgsReader reader(argc, argv);
|
||||||
reader.skip();
|
reader.skip();
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
std::string token = reader.next();
|
std::string token = reader.next();
|
||||||
if (reader.isKeywordArg()) {
|
if (reader.isKeywordArg()) {
|
||||||
if (!perform_keyword(reader, token, paths)) {
|
if (!perform_keyword(reader, token, params)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class EnginePaths;
|
struct CoreParameters;
|
||||||
|
|
||||||
/// @return false if engine start can
|
/// @return false if engine start can
|
||||||
bool parse_cmdline(int argc, char** argv, EnginePaths& paths);
|
bool parse_cmdline(int argc, char** argv, CoreParameters& params);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user