add vctest (WIP)

This commit is contained in:
MihailRis
2024-12-07 15:49:23 +03:00
parent d9bd60f473
commit 5e8805f241
16 changed files with 439 additions and 52 deletions
+15 -1
View File
@@ -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));
+3
View File
@@ -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();
+12
View File
@@ -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;
};
+54
View File
@@ -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
View File
@@ -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
View File
@@ -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();
+37
View File
@@ -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
View File
@@ -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();