add vctest (WIP)
This commit is contained in:
+15
-1
@@ -36,6 +36,7 @@
|
||||
#include "window/Events.hpp"
|
||||
#include "window/input.hpp"
|
||||
#include "window/Window.hpp"
|
||||
#include "interfaces/Process.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
@@ -178,12 +179,25 @@ void Engine::saveScreenshot() {
|
||||
|
||||
void Engine::run() {
|
||||
if (params.headless) {
|
||||
logger.info() << "nothing to do";
|
||||
runTest();
|
||||
} else {
|
||||
mainloop();
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::runTest() {
|
||||
if (params.testFile.empty()) {
|
||||
logger.info() << "nothing to do";
|
||||
return;
|
||||
}
|
||||
logger.info() << "starting test " << params.testFile;
|
||||
auto process = scripting::start_coroutine(params.testFile);
|
||||
while (process->isActive()) {
|
||||
process->update();
|
||||
}
|
||||
logger.info() << "test finished";
|
||||
}
|
||||
|
||||
void Engine::mainloop() {
|
||||
logger.info() << "starting menu screen";
|
||||
setScreen(std::make_shared<MenuScreen>(this));
|
||||
|
||||
@@ -49,6 +49,7 @@ struct CoreParameters {
|
||||
bool headless = false;
|
||||
std::filesystem::path resFolder {"res"};
|
||||
std::filesystem::path userFolder {"."};
|
||||
std::filesystem::path testFile;
|
||||
};
|
||||
|
||||
class Engine : public util::ObjectsKeeper {
|
||||
@@ -93,6 +94,8 @@ public:
|
||||
/// Automatically sets MenuScreen
|
||||
void mainloop();
|
||||
|
||||
void runTest();
|
||||
|
||||
/// @brief Called after assets loading when all engine systems are initialized
|
||||
void onAssetsLoaded();
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
/// @brief Process interface.
|
||||
class Process {
|
||||
public:
|
||||
virtual ~Process() {}
|
||||
|
||||
virtual bool isActive() const = 0;
|
||||
virtual void update() = 0;
|
||||
virtual void waitForEnd() = 0;
|
||||
virtual void terminate() = 0;
|
||||
};
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "util/timeutil.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "interfaces/Process.hpp"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
@@ -71,6 +72,59 @@ void scripting::initialize(Engine* engine) {
|
||||
load_script(fs::path("classes.lua"), true);
|
||||
}
|
||||
|
||||
class LuaCoroutine : public Process {
|
||||
lua::State* L;
|
||||
int id;
|
||||
bool alive = true;
|
||||
public:
|
||||
LuaCoroutine(lua::State* L, int id) : L(L), id(id) {
|
||||
}
|
||||
|
||||
bool isActive() const override {
|
||||
return alive;
|
||||
}
|
||||
|
||||
void update() override {
|
||||
if (lua::getglobal(L, "__vc_resume_coroutine")) {
|
||||
lua::pushinteger(L, id);
|
||||
if (lua::call(L, 1)) {
|
||||
alive = lua::toboolean(L, -1);
|
||||
lua::pop(L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void waitForEnd() override {
|
||||
while (isActive()) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void terminate() override {
|
||||
if (lua::getglobal(L, "__vc_stop_coroutine")) {
|
||||
lua::pushinteger(L, id);
|
||||
lua::pop(L, lua::call(L, 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Process> scripting::start_coroutine(
|
||||
const std::filesystem::path& script
|
||||
) {
|
||||
auto L = lua::get_main_state();
|
||||
if (lua::getglobal(L, "__vc_start_coroutine")) {
|
||||
auto source = files::read_string(script);
|
||||
lua::loadbuffer(L, 0, source, script.filename().u8string());
|
||||
if (lua::call(L, 1)) {
|
||||
int id = lua::tointeger(L, -1);
|
||||
lua::pop(L, 2);
|
||||
return std::make_unique<LuaCoroutine>(L, id);
|
||||
}
|
||||
lua::pop(L);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] scriptenv scripting::get_root_environment() {
|
||||
return std::make_shared<int>(0);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "typedefs.hpp"
|
||||
#include "scripting_functional.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class Engine;
|
||||
class Content;
|
||||
struct ContentPack;
|
||||
@@ -34,6 +32,7 @@ class Entity;
|
||||
struct EntityDef;
|
||||
class GeneratorScript;
|
||||
struct GeneratorDef;
|
||||
class Process;
|
||||
|
||||
namespace scripting {
|
||||
extern Engine* engine;
|
||||
@@ -60,6 +59,10 @@ namespace scripting {
|
||||
|
||||
void process_post_runnables();
|
||||
|
||||
std::unique_ptr<Process> start_coroutine(
|
||||
const std::filesystem::path& script
|
||||
);
|
||||
|
||||
void on_world_load(LevelController* controller);
|
||||
void on_world_tick();
|
||||
void on_world_save();
|
||||
@@ -136,7 +139,7 @@ namespace scripting {
|
||||
void load_content_script(
|
||||
const scriptenv& env,
|
||||
const std::string& prefix,
|
||||
const fs::path& file,
|
||||
const std::filesystem::path& file,
|
||||
const std::string& fileName,
|
||||
block_funcs_set& funcsset
|
||||
);
|
||||
@@ -150,7 +153,7 @@ namespace scripting {
|
||||
void load_content_script(
|
||||
const scriptenv& env,
|
||||
const std::string& prefix,
|
||||
const fs::path& file,
|
||||
const std::filesystem::path& file,
|
||||
const std::string& fileName,
|
||||
item_funcs_set& funcsset
|
||||
);
|
||||
@@ -161,13 +164,13 @@ namespace scripting {
|
||||
/// @param fileName script file path using the engine format
|
||||
void load_entity_component(
|
||||
const std::string& name,
|
||||
const fs::path& file,
|
||||
const std::filesystem::path& file,
|
||||
const std::string& fileName
|
||||
);
|
||||
|
||||
std::unique_ptr<GeneratorScript> load_generator(
|
||||
const GeneratorDef& def,
|
||||
const fs::path& file,
|
||||
const std::filesystem::path& file,
|
||||
const std::string& dirPath
|
||||
);
|
||||
|
||||
@@ -179,7 +182,7 @@ namespace scripting {
|
||||
void load_world_script(
|
||||
const scriptenv& env,
|
||||
const std::string& packid,
|
||||
const fs::path& file,
|
||||
const std::filesystem::path& file,
|
||||
const std::string& fileName,
|
||||
world_funcs_set& funcsset
|
||||
);
|
||||
@@ -193,7 +196,7 @@ namespace scripting {
|
||||
void load_layout_script(
|
||||
const scriptenv& env,
|
||||
const std::string& prefix,
|
||||
const fs::path& file,
|
||||
const std::filesystem::path& file,
|
||||
const std::string& fileName,
|
||||
uidocscript& script
|
||||
);
|
||||
|
||||
+10
-4
@@ -3,17 +3,23 @@
|
||||
#include "util/command_line.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
static debug::Logger logger("main");
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
debug::Logger::init("latest.log");
|
||||
|
||||
CoreParameters coreParameters;
|
||||
if (!parse_cmdline(argc, argv, coreParameters)) {
|
||||
return EXIT_SUCCESS;
|
||||
try {
|
||||
if (!parse_cmdline(argc, argv, coreParameters)) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
} catch (const std::runtime_error& err) {
|
||||
std::cerr << err.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
debug::Logger::init(coreParameters.userFolder.string()+"/latest.log");
|
||||
platform::configure_encoding();
|
||||
try {
|
||||
Engine(std::move(coreParameters)).run();
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
namespace util {
|
||||
class ArgsReader {
|
||||
const char* last = "";
|
||||
char** argv;
|
||||
int argc;
|
||||
int pos = 0;
|
||||
public:
|
||||
ArgsReader(int argc, char** argv) : argv(argv), argc(argc) {
|
||||
}
|
||||
|
||||
void skip() {
|
||||
pos++;
|
||||
}
|
||||
|
||||
bool hasNext() const {
|
||||
return pos < argc && std::strlen(argv[pos]);
|
||||
}
|
||||
|
||||
bool isKeywordArg() const {
|
||||
return last[0] == '-';
|
||||
}
|
||||
|
||||
std::string next() {
|
||||
if (pos >= argc) {
|
||||
throw std::runtime_error("unexpected end");
|
||||
}
|
||||
last = argv[pos];
|
||||
return argv[pos++];
|
||||
}
|
||||
};
|
||||
}
|
||||
+10
-39
@@ -1,48 +1,16 @@
|
||||
#include "command_line.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "files/engine_paths.hpp"
|
||||
#include "util/ArgsReader.hpp"
|
||||
#include "engine.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class ArgsReader {
|
||||
const char* last = "";
|
||||
char** argv;
|
||||
int argc;
|
||||
int pos = 0;
|
||||
public:
|
||||
ArgsReader(int argc, char** argv) : argv(argv), argc(argc) {
|
||||
}
|
||||
|
||||
void skip() {
|
||||
pos++;
|
||||
}
|
||||
|
||||
bool hasNext() const {
|
||||
return pos < argc && strlen(argv[pos]);
|
||||
}
|
||||
|
||||
bool isKeywordArg() const {
|
||||
return last[0] == '-';
|
||||
}
|
||||
|
||||
std::string next() {
|
||||
if (pos >= argc) {
|
||||
throw std::runtime_error("unexpected end");
|
||||
}
|
||||
last = argv[pos];
|
||||
return argv[pos++];
|
||||
}
|
||||
};
|
||||
|
||||
static bool perform_keyword(
|
||||
ArgsReader& reader, const std::string& keyword, CoreParameters& params
|
||||
util::ArgsReader& reader, const std::string& keyword, CoreParameters& params
|
||||
) {
|
||||
if (keyword == "--res") {
|
||||
auto token = reader.next();
|
||||
@@ -53,22 +21,25 @@ static bool perform_keyword(
|
||||
} else if (keyword == "--help" || keyword == "-h") {
|
||||
std::cout << "VoxelEngine command-line arguments:\n";
|
||||
std::cout << " --help - show help\n";
|
||||
std::cout << " --res [path] - set resources directory\n";
|
||||
std::cout << " --dir [path] - set userfiles directory\n";
|
||||
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 << " --test <path> - test script file\n";
|
||||
std::cout << std::endl;
|
||||
return false;
|
||||
} else if (keyword == "--headless") {
|
||||
params.headless = true;
|
||||
} else if (keyword == "--test") {
|
||||
auto token = reader.next();
|
||||
params.testFile = fs::u8path(token);
|
||||
} else {
|
||||
std::cerr << "unknown argument " << keyword << std::endl;
|
||||
return false;
|
||||
throw std::runtime_error("unknown argument " + keyword);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_cmdline(int argc, char** argv, CoreParameters& params) {
|
||||
ArgsReader reader(argc, argv);
|
||||
util::ArgsReader reader(argc, argv);
|
||||
reader.skip();
|
||||
while (reader.hasNext()) {
|
||||
std::string token = reader.next();
|
||||
|
||||
Reference in New Issue
Block a user