migrate from std::filesystem::path to io::path (WIP)
This commit is contained in:
parent
1e22882284
commit
e0314803c0
@ -20,6 +20,8 @@
|
|||||||
#include "Assets.hpp"
|
#include "Assets.hpp"
|
||||||
#include "assetload_funcs.hpp"
|
#include "assetload_funcs.hpp"
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static debug::Logger logger("assets-loader");
|
static debug::Logger logger("assets-loader");
|
||||||
|
|
||||||
AssetsLoader::AssetsLoader(Assets* assets, const ResPaths* paths)
|
AssetsLoader::AssetsLoader(Assets* assets, const ResPaths* paths)
|
||||||
@ -83,22 +85,22 @@ void AssetsLoader::loadNext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLayouts(
|
static void add_layouts(
|
||||||
const scriptenv& env,
|
const scriptenv& env,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const fs::path& folder,
|
const io::path& folder,
|
||||||
AssetsLoader& loader
|
AssetsLoader& loader
|
||||||
) {
|
) {
|
||||||
if (!fs::is_directory(folder)) {
|
if (!io::is_directory(folder)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto& entry : fs::directory_iterator(folder)) {
|
for (auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||||
const fs::path& file = entry.path();
|
io::path file = folder / entry.path().filename().u8string();
|
||||||
if (file.extension().u8string() != ".xml") continue;
|
if (file.extension() != ".xml") continue;
|
||||||
std::string name = prefix + ":" + file.stem().u8string();
|
std::string name = prefix + ":" + file.stem();
|
||||||
loader.add(
|
loader.add(
|
||||||
AssetType::LAYOUT,
|
AssetType::LAYOUT,
|
||||||
file.u8string(),
|
file.string(),
|
||||||
name,
|
name,
|
||||||
std::make_shared<LayoutCfg>(env)
|
std::make_shared<LayoutCfg>(env)
|
||||||
);
|
);
|
||||||
@ -186,7 +188,7 @@ void AssetsLoader::processPreloadList(AssetType tag, const dv::value& list) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetsLoader::processPreloadConfig(const fs::path& file) {
|
void AssetsLoader::processPreloadConfig(const io::path& file) {
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
processPreloadList(AssetType::ATLAS, root["atlases"]);
|
processPreloadList(AssetType::ATLAS, root["atlases"]);
|
||||||
processPreloadList(AssetType::FONT, root["fonts"]);
|
processPreloadList(AssetType::FONT, root["fonts"]);
|
||||||
@ -198,8 +200,8 @@ void AssetsLoader::processPreloadConfig(const fs::path& file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AssetsLoader::processPreloadConfigs(const Content* content) {
|
void AssetsLoader::processPreloadConfigs(const Content* content) {
|
||||||
auto preloadFile = paths->getMainRoot() / fs::path("preload.json");
|
auto preloadFile = paths->getMainRoot() / "preload.json";
|
||||||
if (fs::exists(preloadFile)) {
|
if (io::exists(preloadFile)) {
|
||||||
processPreloadConfig(preloadFile);
|
processPreloadConfig(preloadFile);
|
||||||
}
|
}
|
||||||
if (content == nullptr) {
|
if (content == nullptr) {
|
||||||
@ -210,8 +212,8 @@ void AssetsLoader::processPreloadConfigs(const Content* content) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto& pack = entry.second;
|
const auto& pack = entry.second;
|
||||||
auto preloadFile = pack->getInfo().folder / fs::path("preload.json");
|
auto preloadFile = pack->getInfo().folder / "preload.json";
|
||||||
if (fs::exists(preloadFile)) {
|
if (io::exists(preloadFile)) {
|
||||||
processPreloadConfig(preloadFile);
|
processPreloadConfig(preloadFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,8 +232,8 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
|||||||
for (auto& entry : content->getPacks()) {
|
for (auto& entry : content->getPacks()) {
|
||||||
auto pack = entry.second.get();
|
auto pack = entry.second.get();
|
||||||
auto& info = pack->getInfo();
|
auto& info = pack->getInfo();
|
||||||
fs::path folder = info.folder / fs::path("layouts");
|
io::path folder = info.folder / "layouts";
|
||||||
addLayouts(pack->getEnvironment(), info.id, folder, loader);
|
add_layouts(pack->getEnvironment(), info.id, folder, loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& entry : content->getSkeletons()) {
|
for (auto& entry : content->getSkeletons()) {
|
||||||
@ -274,20 +276,20 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
|||||||
bool AssetsLoader::loadExternalTexture(
|
bool AssetsLoader::loadExternalTexture(
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<std::filesystem::path>& alternatives
|
const std::vector<io::path>& alternatives
|
||||||
) {
|
) {
|
||||||
if (assets->get<Texture>(name) != nullptr) {
|
if (assets->get<Texture>(name) != nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (auto& path : alternatives) {
|
for (auto& path : alternatives) {
|
||||||
if (fs::exists(path)) {
|
if (io::exists(path)) {
|
||||||
try {
|
try {
|
||||||
auto image = imageio::read(path);
|
auto image = imageio::read(path);
|
||||||
assets->store(Texture::from(image.get()), name);
|
assets->store(Texture::from(image.get()), name);
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
logger.error() << "error while loading external "
|
logger.error() << "error while loading external "
|
||||||
<< path.u8string() << ": " << err.what();
|
<< path.string() << ": " << err.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -14,6 +13,7 @@
|
|||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "Assets.hpp"
|
#include "Assets.hpp"
|
||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
class ResPaths;
|
class ResPaths;
|
||||||
class AssetsLoader;
|
class AssetsLoader;
|
||||||
@ -73,7 +73,7 @@ class AssetsLoader {
|
|||||||
AssetType tag, const std::string& name, const dv::value& map
|
AssetType tag, const std::string& name, const dv::value& map
|
||||||
);
|
);
|
||||||
void processPreloadList(AssetType tag, const dv::value& list);
|
void processPreloadList(AssetType tag, const dv::value& list);
|
||||||
void processPreloadConfig(const std::filesystem::path& file);
|
void processPreloadConfig(const io::path& file);
|
||||||
void processPreloadConfigs(const Content* content);
|
void processPreloadConfigs(const Content* content);
|
||||||
public:
|
public:
|
||||||
AssetsLoader(Assets* assets, const ResPaths* paths);
|
AssetsLoader(Assets* assets, const ResPaths* paths);
|
||||||
@ -109,6 +109,6 @@ public:
|
|||||||
static bool loadExternalTexture(
|
static bool loadExternalTexture(
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<std::filesystem::path>& alternatives
|
const std::vector<io::path>& alternatives
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -48,16 +48,14 @@ assetload::postfunc assetload::texture(
|
|||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
) {
|
) {
|
||||||
auto actualFile = paths->find(filename + ".png").u8string();
|
auto actualFile = paths->find(filename + ".png");
|
||||||
try {
|
try {
|
||||||
std::shared_ptr<ImageData> image(
|
std::shared_ptr<ImageData> image(imageio::read(actualFile).release());
|
||||||
imageio::read(fs::u8path(actualFile)).release()
|
|
||||||
);
|
|
||||||
return [name, image, actualFile](auto assets) {
|
return [name, image, actualFile](auto assets) {
|
||||||
assets->store(Texture::from(image.get()), name);
|
assets->store(Texture::from(image.get()), name);
|
||||||
};
|
};
|
||||||
} catch (const std::runtime_error& err) {
|
} catch (const std::runtime_error& err) {
|
||||||
logger.error() << actualFile << ": " << err.what();
|
logger.error() << actualFile.string() << ": " << err.what();
|
||||||
return [](auto) {};
|
return [](auto) {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,8 +67,8 @@ assetload::postfunc assetload::shader(
|
|||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
) {
|
) {
|
||||||
fs::path vertexFile = paths->find(filename + ".glslv");
|
io::path vertexFile = paths->find(filename + ".glslv");
|
||||||
fs::path fragmentFile = paths->find(filename + ".glslf");
|
io::path fragmentFile = paths->find(filename + ".glslf");
|
||||||
|
|
||||||
std::string vertexSource = io::read_string(vertexFile);
|
std::string vertexSource = io::read_string(vertexFile);
|
||||||
std::string fragmentSource = io::read_string(fragmentFile);
|
std::string fragmentSource = io::read_string(fragmentFile);
|
||||||
@ -82,8 +80,8 @@ assetload::postfunc assetload::shader(
|
|||||||
return [=](auto assets) {
|
return [=](auto assets) {
|
||||||
assets->store(
|
assets->store(
|
||||||
Shader::create(
|
Shader::create(
|
||||||
vertexFile.u8string(),
|
vertexFile.string(),
|
||||||
fragmentFile.u8string(),
|
fragmentFile.string(),
|
||||||
vertexSource,
|
vertexSource,
|
||||||
fragmentSource
|
fragmentSource
|
||||||
),
|
),
|
||||||
@ -92,8 +90,8 @@ assetload::postfunc assetload::shader(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool append_atlas(AtlasBuilder& atlas, const fs::path& file) {
|
static bool append_atlas(AtlasBuilder& atlas, const io::path& file) {
|
||||||
std::string name = file.stem().string();
|
std::string name = file.stem();
|
||||||
// skip duplicates
|
// skip duplicates
|
||||||
if (atlas.has(name)) {
|
if (atlas.has(name)) {
|
||||||
return false;
|
return false;
|
||||||
@ -114,19 +112,19 @@ assetload::postfunc assetload::atlas(
|
|||||||
auto atlasConfig = std::dynamic_pointer_cast<AtlasCfg>(config);
|
auto atlasConfig = std::dynamic_pointer_cast<AtlasCfg>(config);
|
||||||
if (atlasConfig && atlasConfig->type == AtlasType::SEPARATE) {
|
if (atlasConfig && atlasConfig->type == AtlasType::SEPARATE) {
|
||||||
for (const auto& file : paths->listdir(directory)) {
|
for (const auto& file : paths->listdir(directory)) {
|
||||||
if (!imageio::is_read_supported(file.extension().u8string()))
|
if (!imageio::is_read_supported(file.extension()))
|
||||||
continue;
|
continue;
|
||||||
loader->add(
|
loader->add(
|
||||||
AssetType::TEXTURE,
|
AssetType::TEXTURE,
|
||||||
directory + "/" + file.stem().u8string(),
|
directory + "/" + file.stem(),
|
||||||
name + "/" + file.stem().u8string()
|
name + "/" + file.stem()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return [](auto){};
|
return [](auto){};
|
||||||
}
|
}
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
for (const auto& file : paths->listdir(directory)) {
|
for (const auto& file : paths->listdir(directory)) {
|
||||||
if (!imageio::is_read_supported(file.extension().u8string())) continue;
|
if (!imageio::is_read_supported(file.extension())) continue;
|
||||||
if (!append_atlas(builder, file)) continue;
|
if (!append_atlas(builder, file)) continue;
|
||||||
}
|
}
|
||||||
std::set<std::string> names = builder.getNames();
|
std::set<std::string> names = builder.getNames();
|
||||||
@ -151,7 +149,7 @@ assetload::postfunc assetload::font(
|
|||||||
for (size_t i = 0; i <= 1024; i++) {
|
for (size_t i = 0; i <= 1024; i++) {
|
||||||
std::string pagefile = filename + "_" + std::to_string(i) + ".png";
|
std::string pagefile = filename + "_" + std::to_string(i) + ".png";
|
||||||
auto file = paths->find(pagefile);
|
auto file = paths->find(pagefile);
|
||||||
if (fs::exists(file)) {
|
if (io::exists(file)) {
|
||||||
pages->push_back(imageio::read(file));
|
pages->push_back(imageio::read(file));
|
||||||
} else if (i == 0) {
|
} else if (i == 0) {
|
||||||
throw std::runtime_error("font must have page 0");
|
throw std::runtime_error("font must have page 0");
|
||||||
@ -222,13 +220,13 @@ assetload::postfunc assetload::sound(
|
|||||||
extension = extensions[i];
|
extension = extensions[i];
|
||||||
// looking for 'sound_name' as base sound
|
// looking for 'sound_name' as base sound
|
||||||
auto soundFile = paths->find(file + extension);
|
auto soundFile = paths->find(file + extension);
|
||||||
if (fs::exists(soundFile)) {
|
if (io::exists(soundFile)) {
|
||||||
baseSound = audio::load_sound(soundFile, keepPCM);
|
baseSound = audio::load_sound(soundFile, keepPCM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// looking for 'sound_name_0' as base sound
|
// looking for 'sound_name_0' as base sound
|
||||||
auto variantFile = paths->find(file + "_0" + extension);
|
auto variantFile = paths->find(file + "_0" + extension);
|
||||||
if (fs::exists(variantFile)) {
|
if (io::exists(variantFile)) {
|
||||||
baseSound = audio::load_sound(variantFile, keepPCM);
|
baseSound = audio::load_sound(variantFile, keepPCM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -241,7 +239,7 @@ assetload::postfunc assetload::sound(
|
|||||||
for (uint i = 1;; i++) {
|
for (uint i = 1;; i++) {
|
||||||
auto variantFile =
|
auto variantFile =
|
||||||
paths->find(file + "_" + std::to_string(i) + extension);
|
paths->find(file + "_" + std::to_string(i) + extension);
|
||||||
if (!fs::exists(variantFile)) {
|
if (!io::exists(variantFile)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
|
baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
|
||||||
@ -272,9 +270,9 @@ assetload::postfunc assetload::model(
|
|||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
) {
|
) {
|
||||||
auto path = paths->find(file + ".vec3");
|
auto path = paths->find(file + ".vec3");
|
||||||
if (fs::exists(path)) {
|
if (io::exists(path)) {
|
||||||
auto bytes = io::read_bytes_buffer(path);
|
auto bytes = io::read_bytes_buffer(path);
|
||||||
auto modelVEC3 = std::make_shared<vec3::File>(vec3::load(path.u8string(), bytes));
|
auto modelVEC3 = std::make_shared<vec3::File>(vec3::load(path.string(), bytes));
|
||||||
return [loader, name, modelVEC3=std::move(modelVEC3)](Assets* assets) {
|
return [loader, name, modelVEC3=std::move(modelVEC3)](Assets* assets) {
|
||||||
for (auto& [modelName, model] : modelVEC3->models) {
|
for (auto& [modelName, model] : modelVEC3->models) {
|
||||||
request_textures(loader, model.model);
|
request_textures(loader, model.model);
|
||||||
@ -294,7 +292,7 @@ assetload::postfunc assetload::model(
|
|||||||
path = paths->find(file + ".obj");
|
path = paths->find(file + ".obj");
|
||||||
auto text = io::read_string(path);
|
auto text = io::read_string(path);
|
||||||
try {
|
try {
|
||||||
auto model = obj::parse(path.u8string(), text).release();
|
auto model = obj::parse(path.string(), text).release();
|
||||||
return [=](Assets* assets) {
|
return [=](Assets* assets) {
|
||||||
request_textures(loader, *model);
|
request_textures(loader, *model);
|
||||||
assets->store(std::unique_ptr<model::Model>(model), name);
|
assets->store(std::unique_ptr<model::Model>(model), name);
|
||||||
@ -394,21 +392,21 @@ static bool load_animation(
|
|||||||
std::string animsDir = directory + "/animation";
|
std::string animsDir = directory + "/animation";
|
||||||
|
|
||||||
for (const auto& folder : paths->listdir(animsDir)) {
|
for (const auto& folder : paths->listdir(animsDir)) {
|
||||||
if (!fs::is_directory(folder)) continue;
|
if (!io::is_directory(folder)) continue;
|
||||||
if (folder.filename().u8string() != name) continue;
|
if (folder.name() != name) continue;
|
||||||
if (fs::is_empty(folder)) continue;
|
//FIXME: if (fs::is_empty(folder)) continue;
|
||||||
|
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
append_atlas(builder, paths->find(directory + "/" + name + ".png"));
|
append_atlas(builder, paths->find(directory + "/" + name + ".png"));
|
||||||
|
|
||||||
std::vector<std::pair<std::string, int>> frameList;
|
std::vector<std::pair<std::string, int>> frameList;
|
||||||
std::string animFile = folder.u8string() + "/animation.json";
|
std::string animFile = folder.string() + "/animation.json";
|
||||||
if (fs::exists(animFile)) {
|
if (io::exists(animFile)) {
|
||||||
read_anim_file(animFile, frameList);
|
read_anim_file(animFile, frameList);
|
||||||
}
|
}
|
||||||
for (const auto& file : paths->listdir(animsDir + "/" + name)) {
|
for (const auto& file : paths->listdir(animsDir + "/" + name)) {
|
||||||
if (!frameList.empty() &&
|
if (!frameList.empty() &&
|
||||||
!contains(frameList, file.stem().u8string())) {
|
!contains(frameList, file.stem())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!append_atlas(builder, file)) continue;
|
if (!append_atlas(builder, file)) continue;
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "io/io.hpp"
|
||||||
#include "coders/ogg.hpp"
|
#include "coders/ogg.hpp"
|
||||||
#include "coders/wav.hpp"
|
#include "coders/wav.hpp"
|
||||||
#include "AL/ALAudio.hpp"
|
#include "AL/ALAudio.hpp"
|
||||||
@ -181,11 +182,11 @@ void audio::initialize(bool enabled, AudioSettings& settings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PCM> audio::load_PCM(const fs::path& file, bool headerOnly) {
|
std::unique_ptr<PCM> audio::load_PCM(const io::path& file, bool headerOnly) {
|
||||||
if (!fs::exists(file)) {
|
if (!io::exists(file)) {
|
||||||
throw std::runtime_error("file not found '" + file.u8string() + "'");
|
throw std::runtime_error("file not found '" + file.string() + "'");
|
||||||
}
|
}
|
||||||
std::string ext = file.extension().u8string();
|
std::string ext = file.extension();
|
||||||
if (ext == ".wav" || ext == ".WAV") {
|
if (ext == ".wav" || ext == ".WAV") {
|
||||||
return wav::load_pcm(file, headerOnly);
|
return wav::load_pcm(file, headerOnly);
|
||||||
} else if (ext == ".ogg" || ext == ".OGG") {
|
} else if (ext == ".ogg" || ext == ".OGG") {
|
||||||
@ -194,7 +195,7 @@ std::unique_ptr<PCM> audio::load_PCM(const fs::path& file, bool headerOnly) {
|
|||||||
throw std::runtime_error("unsupported audio format");
|
throw std::runtime_error("unsupported audio format");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Sound> audio::load_sound(const fs::path& file, bool keepPCM) {
|
std::unique_ptr<Sound> audio::load_sound(const io::path& file, bool keepPCM) {
|
||||||
std::shared_ptr<PCM> pcm(
|
std::shared_ptr<PCM> pcm(
|
||||||
load_PCM(file, !keepPCM && backend->isDummy()).release()
|
load_PCM(file, !keepPCM && backend->isDummy()).release()
|
||||||
);
|
);
|
||||||
@ -207,8 +208,8 @@ std::unique_ptr<Sound> audio::create_sound(
|
|||||||
return backend->createSound(std::move(pcm), keepPCM);
|
return backend->createSound(std::move(pcm), keepPCM);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PCMStream> audio::open_PCM_stream(const fs::path& file) {
|
std::unique_ptr<PCMStream> audio::open_PCM_stream(const io::path& file) {
|
||||||
std::string ext = file.extension().u8string();
|
std::string ext = file.extension();
|
||||||
if (ext == ".wav" || ext == ".WAV") {
|
if (ext == ".wav" || ext == ".WAV") {
|
||||||
return wav::create_stream(file);
|
return wav::create_stream(file);
|
||||||
} else if (ext == ".ogg" || ext == ".OGG") {
|
} else if (ext == ".ogg" || ext == ".OGG") {
|
||||||
@ -218,7 +219,7 @@ std::unique_ptr<PCMStream> audio::open_PCM_stream(const fs::path& file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Stream> audio::open_stream(
|
std::unique_ptr<Stream> audio::open_stream(
|
||||||
const fs::path& file, bool keepSource
|
const io::path& file, bool keepSource
|
||||||
) {
|
) {
|
||||||
if (!keepSource && backend->isDummy()) {
|
if (!keepSource && backend->isDummy()) {
|
||||||
auto header = load_PCM(file, true);
|
auto header = load_PCM(file, true);
|
||||||
@ -338,7 +339,7 @@ speakerid_t audio::play(
|
|||||||
}
|
}
|
||||||
|
|
||||||
speakerid_t audio::play_stream(
|
speakerid_t audio::play_stream(
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
glm::vec3 position,
|
glm::vec3 position,
|
||||||
bool relative,
|
bool relative,
|
||||||
float volume,
|
float volume,
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "io/fwd.hpp"
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
/// @brief playing speaker uid
|
/// @brief playing speaker uid
|
||||||
@ -365,7 +363,7 @@ namespace audio {
|
|||||||
/// @param headerOnly read header only
|
/// @param headerOnly read header only
|
||||||
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
||||||
/// @return PCM audio data
|
/// @return PCM audio data
|
||||||
std::unique_ptr<PCM> load_PCM(const fs::path& file, bool headerOnly);
|
std::unique_ptr<PCM> load_PCM(const io::path& file, bool headerOnly);
|
||||||
|
|
||||||
/// @brief Load sound from file
|
/// @brief Load sound from file
|
||||||
/// @param file audio file path
|
/// @param file audio file path
|
||||||
@ -373,7 +371,7 @@ namespace audio {
|
|||||||
/// Sound::getPCM
|
/// Sound::getPCM
|
||||||
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
||||||
/// @return new Sound instance
|
/// @return new Sound instance
|
||||||
std::unique_ptr<Sound> load_sound(const fs::path& file, bool keepPCM);
|
std::unique_ptr<Sound> load_sound(const io::path& file, bool keepPCM);
|
||||||
|
|
||||||
/// @brief Create new sound from PCM data
|
/// @brief Create new sound from PCM data
|
||||||
/// @param pcm PCM data
|
/// @param pcm PCM data
|
||||||
@ -386,14 +384,14 @@ namespace audio {
|
|||||||
/// @param file audio file path
|
/// @param file audio file path
|
||||||
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
||||||
/// @return new PCMStream instance
|
/// @return new PCMStream instance
|
||||||
std::unique_ptr<PCMStream> open_PCM_stream(const fs::path& file);
|
std::unique_ptr<PCMStream> open_PCM_stream(const io::path& file);
|
||||||
|
|
||||||
/// @brief Open new audio stream from file
|
/// @brief Open new audio stream from file
|
||||||
/// @param file audio file path
|
/// @param file audio file path
|
||||||
/// @param keepSource store PCMStream in stream to make it accessible with
|
/// @param keepSource store PCMStream in stream to make it accessible with
|
||||||
/// Stream::getSource
|
/// Stream::getSource
|
||||||
/// @return new Stream instance
|
/// @return new Stream instance
|
||||||
std::unique_ptr<Stream> open_stream(const fs::path& file, bool keepSource);
|
std::unique_ptr<Stream> open_stream(const io::path& file, bool keepSource);
|
||||||
|
|
||||||
/// @brief Open new audio stream from source
|
/// @brief Open new audio stream from source
|
||||||
/// @param stream PCM data source
|
/// @param stream PCM data source
|
||||||
@ -464,7 +462,7 @@ namespace audio {
|
|||||||
/// @param channel channel index
|
/// @param channel channel index
|
||||||
/// @return speaker id or 0
|
/// @return speaker id or 0
|
||||||
speakerid_t play_stream(
|
speakerid_t play_stream(
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
glm::vec3 position,
|
glm::vec3 position,
|
||||||
bool relative,
|
bool relative,
|
||||||
float volume,
|
float volume,
|
||||||
|
|||||||
@ -6,12 +6,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "io/engine_paths.hpp"
|
#include "io/engine_paths.hpp"
|
||||||
#include "io/io.hpp"
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
void GLSLExtension::setVersion(std::string version) {
|
void GLSLExtension::setVersion(std::string version) {
|
||||||
this->version = std::move(version);
|
this->version = std::move(version);
|
||||||
}
|
}
|
||||||
@ -21,7 +18,7 @@ void GLSLExtension::setPaths(const ResPaths* paths) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GLSLExtension::loadHeader(const std::string& name) {
|
void GLSLExtension::loadHeader(const std::string& name) {
|
||||||
fs::path file = paths->find("shaders/lib/" + name + ".glsl");
|
io::path file = paths->find("shaders/lib/" + name + ".glsl");
|
||||||
std::string source = io::read_string(file);
|
std::string source = io::read_string(file);
|
||||||
addHeader(name, "");
|
addHeader(name, "");
|
||||||
addHeader(name, process(file, source, true));
|
addHeader(name, process(file, source, true));
|
||||||
@ -66,7 +63,7 @@ void GLSLExtension::undefine(const std::string& name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline std::runtime_error parsing_error(
|
inline std::runtime_error parsing_error(
|
||||||
const fs::path& file, uint linenum, const std::string& message
|
const io::path& file, uint linenum, const std::string& message
|
||||||
) {
|
) {
|
||||||
return std::runtime_error(
|
return std::runtime_error(
|
||||||
"file " + file.string() + ": " + message + " at line " +
|
"file " + file.string() + ": " + message + " at line " +
|
||||||
@ -75,7 +72,7 @@ inline std::runtime_error parsing_error(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void parsing_warning(
|
inline void parsing_warning(
|
||||||
const fs::path& file, uint linenum, const std::string& message
|
const io::path& file, uint linenum, const std::string& message
|
||||||
) {
|
) {
|
||||||
std::cerr << "file " + file.string() + ": warning: " + message +
|
std::cerr << "file " + file.string() + ": warning: " + message +
|
||||||
" at line " + std::to_string(linenum)
|
" at line " + std::to_string(linenum)
|
||||||
@ -87,7 +84,7 @@ inline void source_line(std::stringstream& ss, uint linenum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GLSLExtension::process(
|
std::string GLSLExtension::process(
|
||||||
const fs::path& file, const std::string& source, bool header
|
const io::path& file, const std::string& source, bool header
|
||||||
) {
|
) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "io/io.hpp"
|
||||||
|
|
||||||
class ResPaths;
|
class ResPaths;
|
||||||
|
|
||||||
class GLSLExtension {
|
class GLSLExtension {
|
||||||
@ -29,7 +30,7 @@ public:
|
|||||||
bool hasDefine(const std::string& name) const;
|
bool hasDefine(const std::string& name) const;
|
||||||
|
|
||||||
std::string process(
|
std::string process(
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& source,
|
const std::string& source,
|
||||||
bool header = false
|
bool header = false
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "imageio.hpp"
|
#include "imageio.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@ -8,8 +7,6 @@
|
|||||||
#include "io/io.hpp"
|
#include "io/io.hpp"
|
||||||
#include "png.hpp"
|
#include "png.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
using image_reader =
|
using image_reader =
|
||||||
std::function<std::unique_ptr<ImageData>(const ubyte*, size_t)>;
|
std::function<std::unique_ptr<ImageData>(const ubyte*, size_t)>;
|
||||||
using image_writer = std::function<void(const std::string&, const ImageData*)>;
|
using image_writer = std::function<void(const std::string&, const ImageData*)>;
|
||||||
@ -30,33 +27,29 @@ bool imageio::is_write_supported(const std::string& extension) {
|
|||||||
return writers.find(extension) != writers.end();
|
return writers.find(extension) != writers.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string extensionOf(const std::string& filename) {
|
std::unique_ptr<ImageData> imageio::read(const io::path& file) {
|
||||||
return fs::u8path(filename).extension().u8string();
|
auto found = readers.find(file.extension());
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ImageData> imageio::read(const fs::path& filename) {
|
|
||||||
auto found = readers.find(extensionOf(filename.u8string()));
|
|
||||||
if (found == readers.end()) {
|
if (found == readers.end()) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"file format is not supported (read): " + filename.u8string()
|
"file format is not supported (read): " + file.string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
auto bytes = io::read_bytes_buffer(filename);
|
auto bytes = io::read_bytes_buffer(file);
|
||||||
try {
|
try {
|
||||||
return std::unique_ptr<ImageData>(found->second(bytes.data(), bytes.size()));
|
return std::unique_ptr<ImageData>(found->second(bytes.data(), bytes.size()));
|
||||||
} catch (const std::runtime_error& err) {
|
} catch (const std::runtime_error& err) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"could not to load image " + filename.u8string() + ": " + err.what()
|
"could not to load image " + file.string() + ": " + err.what()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void imageio::write(const std::string& filename, const ImageData* image) {
|
void imageio::write(const io::path& file, const ImageData* image) {
|
||||||
auto found = writers.find(extensionOf(filename));
|
auto found = writers.find(file.extension());
|
||||||
if (found == writers.end()) {
|
if (found == writers.end()) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"file format is not supported (write): " + filename
|
"file format is not supported (write): " + file.string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return found->second(filename, image);
|
return found->second(io::resolve(file).u8string(), image);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
|
||||||
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
class ImageData;
|
class ImageData;
|
||||||
|
|
||||||
@ -12,6 +13,6 @@ namespace imageio {
|
|||||||
bool is_read_supported(const std::string& extension);
|
bool is_read_supported(const std::string& extension);
|
||||||
bool is_write_supported(const std::string& extension);
|
bool is_write_supported(const std::string& extension);
|
||||||
|
|
||||||
std::unique_ptr<ImageData> read(const std::filesystem::path& file);
|
std::unique_ptr<ImageData> read(const io::path& file);
|
||||||
void write(const std::string& filename, const ImageData* image);
|
void write(const io::path& file, const ImageData* image);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "io/io.hpp"
|
||||||
#include "audio/audio.hpp"
|
#include "audio/audio.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
@ -43,11 +44,11 @@ static inline std::string vorbis_error_message(int code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<audio::PCM> ogg::load_pcm(
|
std::unique_ptr<audio::PCM> ogg::load_pcm(
|
||||||
const fs::path& file, bool headerOnly
|
const io::path& file, bool headerOnly
|
||||||
) {
|
) {
|
||||||
OggVorbis_File vf;
|
OggVorbis_File vf;
|
||||||
int code;
|
int code;
|
||||||
if ((code = ov_fopen(file.u8string().c_str(), &vf))) {
|
if ((code = ov_fopen(io::resolve(file).u8string().c_str(), &vf))) {
|
||||||
throw std::runtime_error("vorbis: " + vorbis_error_message(code));
|
throw std::runtime_error("vorbis: " + vorbis_error_message(code));
|
||||||
}
|
}
|
||||||
std::vector<char> data;
|
std::vector<char> data;
|
||||||
@ -166,10 +167,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<PCMStream> ogg::create_stream(const fs::path& file) {
|
std::unique_ptr<PCMStream> ogg::create_stream(const io::path& file) {
|
||||||
OggVorbis_File vf;
|
OggVorbis_File vf;
|
||||||
int code;
|
int code;
|
||||||
if ((code = ov_fopen(file.u8string().c_str(), &vf))) {
|
if ((code = ov_fopen(io::resolve(file).u8string().c_str(), &vf))) {
|
||||||
throw std::runtime_error("vorbis: " + vorbis_error_message(code));
|
throw std::runtime_error("vorbis: " + vorbis_error_message(code));
|
||||||
}
|
}
|
||||||
return std::make_unique<OggStream>(vf);
|
return std::make_unique<OggStream>(vf);
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
struct PCM;
|
struct PCM;
|
||||||
@ -9,9 +11,9 @@ namespace audio {
|
|||||||
|
|
||||||
namespace ogg {
|
namespace ogg {
|
||||||
std::unique_ptr<audio::PCM> load_pcm(
|
std::unique_ptr<audio::PCM> load_pcm(
|
||||||
const std::filesystem::path& file, bool headerOnly
|
const io::path& file, bool headerOnly
|
||||||
);
|
);
|
||||||
std::unique_ptr<audio::PCMStream> create_stream(
|
std::unique_ptr<audio::PCMStream> create_stream(
|
||||||
const std::filesystem::path& file
|
const io::path& file
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -212,7 +212,7 @@ std::unique_ptr<Texture> png::load_texture(const ubyte* bytes, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Texture> png::load_texture(const std::string& filename) {
|
std::unique_ptr<Texture> png::load_texture(const std::string& filename) {
|
||||||
auto bytes = io::read_bytes_buffer(fs::u8path(filename));
|
auto bytes = io::read_bytes_buffer(filename);
|
||||||
try {
|
try {
|
||||||
return load_texture(bytes.data(), bytes.size());
|
return load_texture(bytes.data(), bytes.size());
|
||||||
} catch (const std::runtime_error& err) {
|
} catch (const std::runtime_error& err) {
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "io/io.hpp"
|
||||||
#include "audio/audio.hpp"
|
#include "audio/audio.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
|
|
||||||
@ -118,11 +119,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<audio::PCMStream> wav::create_stream(const fs::path& file) {
|
std::unique_ptr<audio::PCMStream> wav::create_stream(const io::path& file) {
|
||||||
std::ifstream in(file, std::ios::binary);
|
std::ifstream in(io::resolve(file), std::ios::binary);
|
||||||
if (!in.is_open()) {
|
if (!in.is_open()) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"could not to open file '" + file.u8string() + "'"
|
"could not to open file '" + file.string() + "'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +235,7 @@ std::unique_ptr<audio::PCMStream> wav::create_stream(const fs::path& file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<audio::PCM> wav::load_pcm(
|
std::unique_ptr<audio::PCM> wav::load_pcm(
|
||||||
const fs::path& file, bool headerOnly
|
const io::path& file, bool headerOnly
|
||||||
) {
|
) {
|
||||||
auto stream = wav::create_stream(file);
|
auto stream = wav::create_stream(file);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
struct PCM;
|
struct PCM;
|
||||||
@ -9,9 +11,9 @@ namespace audio {
|
|||||||
|
|
||||||
namespace wav {
|
namespace wav {
|
||||||
std::unique_ptr<audio::PCM> load_pcm(
|
std::unique_ptr<audio::PCM> load_pcm(
|
||||||
const std::filesystem::path& file, bool headerOnly
|
const io::path& file, bool headerOnly
|
||||||
);
|
);
|
||||||
std::unique_ptr<audio::PCMStream> create_stream(
|
std::unique_ptr<audio::PCMStream> create_stream(
|
||||||
const std::filesystem::path& file
|
const io::path& file
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,55 +43,57 @@ ContentLoader::ContentLoader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void detect_defs(
|
static void detect_defs(
|
||||||
const fs::path& folder,
|
const io::path& folder,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
std::vector<std::string>& detected
|
std::vector<std::string>& detected
|
||||||
) {
|
) {
|
||||||
if (fs::is_directory(folder)) {
|
if (!io::is_directory(folder)) {
|
||||||
for (const auto& entry : fs::directory_iterator(folder)) {
|
return;
|
||||||
const fs::path& file = entry.path();
|
}
|
||||||
std::string name = file.stem().string();
|
for (const auto& entry : std::filesystem::directory_iterator(io::resolve(folder))) {
|
||||||
if (name[0] == '_') {
|
io::path file = folder / entry.path().filename().u8string();
|
||||||
continue;
|
std::string name = file.stem();
|
||||||
}
|
if (name[0] == '_') {
|
||||||
if (fs::is_regular_file(file) && io::is_data_file(file)) {
|
continue;
|
||||||
auto map = io::read_object(file);
|
}
|
||||||
std::string id = prefix.empty() ? name : prefix + ":" + name;
|
if (io::is_regular_file(file) && io::is_data_file(file)) {
|
||||||
detected.emplace_back(id);
|
auto map = io::read_object(file);
|
||||||
} else if (fs::is_directory(file) &&
|
std::string id = prefix.empty() ? name : prefix + ":" + name;
|
||||||
file.extension() != fs::u8path(".files")) {
|
detected.emplace_back(id);
|
||||||
detect_defs(file, name, detected);
|
} else if (io::is_directory(file) &&
|
||||||
}
|
file.extension() != fs::u8path(".files")) {
|
||||||
|
detect_defs(file, name, detected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void detect_defs_pairs(
|
static void detect_defs_pairs(
|
||||||
const fs::path& folder,
|
const io::path& folder,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
std::vector<std::tuple<std::string, std::string>>& detected
|
std::vector<std::tuple<std::string, std::string>>& detected
|
||||||
) {
|
) {
|
||||||
if (fs::is_directory(folder)) {
|
if (!io::is_directory(folder)) {
|
||||||
for (const auto& entry : fs::directory_iterator(folder)) {
|
return;
|
||||||
const fs::path& file = entry.path();
|
}
|
||||||
std::string name = file.stem().string();
|
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||||
if (name[0] == '_') {
|
io::path file = folder / entry.path().filename().u8string();
|
||||||
continue;
|
std::string name = file.stem();
|
||||||
}
|
if (name[0] == '_') {
|
||||||
if (fs::is_regular_file(file) && io::is_data_file(file)) {
|
continue;
|
||||||
try {
|
}
|
||||||
auto map = io::read_object(file);
|
if (io::is_regular_file(file) && io::is_data_file(file)) {
|
||||||
auto id = prefix.empty() ? name : prefix + ":" + name;
|
try {
|
||||||
auto caption = util::id_to_caption(id);
|
auto map = io::read_object(file);
|
||||||
map.at("caption").get(caption);
|
auto id = prefix.empty() ? name : prefix + ":" + name;
|
||||||
detected.emplace_back(id, name);
|
auto caption = util::id_to_caption(id);
|
||||||
} catch (const std::runtime_error& err) {
|
map.at("caption").get(caption);
|
||||||
logger.error() << err.what();
|
detected.emplace_back(id, name);
|
||||||
}
|
} catch (const std::runtime_error& err) {
|
||||||
} else if (fs::is_directory(file) &&
|
logger.error() << err.what();
|
||||||
file.extension() != fs::u8path(".files")) {
|
|
||||||
detect_defs_pairs(file, name, detected);
|
|
||||||
}
|
}
|
||||||
|
} else if (io::is_directory(file) &&
|
||||||
|
file.extension() != fs::u8path(".files")) {
|
||||||
|
detect_defs_pairs(file, name, detected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +108,7 @@ std::vector<std::tuple<std::string, std::string>> ContentLoader::scanContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ContentLoader::fixPackIndices(
|
bool ContentLoader::fixPackIndices(
|
||||||
const fs::path& folder,
|
const io::path& folder,
|
||||||
dv::value& indicesRoot,
|
dv::value& indicesRoot,
|
||||||
const std::string& contentSection
|
const std::string& contentSection
|
||||||
) {
|
) {
|
||||||
@ -146,7 +148,7 @@ void ContentLoader::fixPackIndices() {
|
|||||||
auto entitiesFolder = folder / ContentPack::ENTITIES_FOLDER;
|
auto entitiesFolder = folder / ContentPack::ENTITIES_FOLDER;
|
||||||
|
|
||||||
dv::value root;
|
dv::value root;
|
||||||
if (fs::is_regular_file(contentFile)) {
|
if (io::is_regular_file(contentFile)) {
|
||||||
root = io::read_json(contentFile);
|
root = io::read_json(contentFile);
|
||||||
} else {
|
} else {
|
||||||
root = dv::object();
|
root = dv::object();
|
||||||
@ -213,7 +215,7 @@ static void process_method(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadBlock(
|
void ContentLoader::loadBlock(
|
||||||
Block& def, const std::string& name, const fs::path& file
|
Block& def, const std::string& name, const io::path& file
|
||||||
) {
|
) {
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
if (def.properties == nullptr) {
|
if (def.properties == nullptr) {
|
||||||
@ -402,7 +404,7 @@ void ContentLoader::loadBlock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadItem(
|
void ContentLoader::loadItem(
|
||||||
ItemDef& def, const std::string& name, const fs::path& file
|
ItemDef& def, const std::string& name, const io::path& file
|
||||||
) {
|
) {
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
def.properties = root;
|
def.properties = root;
|
||||||
@ -446,7 +448,7 @@ void ContentLoader::loadItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadEntity(
|
void ContentLoader::loadEntity(
|
||||||
EntityDef& def, const std::string& name, const fs::path& file
|
EntityDef& def, const std::string& name, const io::path& file
|
||||||
) {
|
) {
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
|
|
||||||
@ -518,16 +520,16 @@ void ContentLoader::loadEntity(
|
|||||||
EntityDef& def, const std::string& full, const std::string& name
|
EntityDef& def, const std::string& full, const std::string& name
|
||||||
) {
|
) {
|
||||||
auto folder = pack->folder;
|
auto folder = pack->folder;
|
||||||
auto configFile = folder / fs::path("entities/" + name + ".json");
|
auto configFile = folder / ("entities/" + name + ".json");
|
||||||
if (fs::exists(configFile)) loadEntity(def, full, configFile);
|
if (io::exists(configFile)) loadEntity(def, full, configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadBlock(
|
void ContentLoader::loadBlock(
|
||||||
Block& def, const std::string& full, const std::string& name
|
Block& def, const std::string& full, const std::string& name
|
||||||
) {
|
) {
|
||||||
auto folder = pack->folder;
|
auto folder = pack->folder;
|
||||||
auto configFile = folder / fs::path("blocks/" + name + ".json");
|
auto configFile = folder / ("blocks/" + name + ".json");
|
||||||
if (fs::exists(configFile)) loadBlock(def, full, configFile);
|
if (io::exists(configFile)) loadBlock(def, full, configFile);
|
||||||
|
|
||||||
if (!def.hidden) {
|
if (!def.hidden) {
|
||||||
bool created;
|
bool created;
|
||||||
@ -549,8 +551,8 @@ void ContentLoader::loadItem(
|
|||||||
ItemDef& def, const std::string& full, const std::string& name
|
ItemDef& def, const std::string& full, const std::string& name
|
||||||
) {
|
) {
|
||||||
auto folder = pack->folder;
|
auto folder = pack->folder;
|
||||||
auto configFile = folder / fs::path("items/" + name + ".json");
|
auto configFile = folder / ("items/" + name + ".json");
|
||||||
if (fs::exists(configFile)) loadItem(def, full, configFile);
|
if (io::exists(configFile)) loadItem(def, full, configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::tuple<std::string, std::string, std::string> create_unit_id(
|
static std::tuple<std::string, std::string, std::string> create_unit_id(
|
||||||
@ -566,7 +568,7 @@ static std::tuple<std::string, std::string, std::string> create_unit_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadBlockMaterial(
|
void ContentLoader::loadBlockMaterial(
|
||||||
BlockMaterial& def, const fs::path& file
|
BlockMaterial& def, const io::path& file
|
||||||
) {
|
) {
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
root.at("steps-sound").get(def.stepsSound);
|
root.at("steps-sound").get(def.stepsSound);
|
||||||
@ -577,9 +579,9 @@ void ContentLoader::loadBlockMaterial(
|
|||||||
void ContentLoader::loadContent(const dv::value& root) {
|
void ContentLoader::loadContent(const dv::value& root) {
|
||||||
std::vector<std::pair<std::string, std::string>> pendingDefs;
|
std::vector<std::pair<std::string, std::string>> pendingDefs;
|
||||||
auto getJsonParent = [this](const std::string& prefix, const std::string& name) {
|
auto getJsonParent = [this](const std::string& prefix, const std::string& name) {
|
||||||
auto configFile = pack->folder / fs::path(prefix + "/" + name + ".json");
|
auto configFile = pack->folder / (prefix + "/" + name + ".json");
|
||||||
std::string parent;
|
std::string parent;
|
||||||
if (fs::exists(configFile)) {
|
if (io::exists(configFile)) {
|
||||||
auto root = io::read_json(configFile);
|
auto root = io::read_json(configFile);
|
||||||
root.at("parent").get(parent);
|
root.at("parent").get(parent);
|
||||||
}
|
}
|
||||||
@ -740,16 +742,17 @@ void ContentLoader::loadContent(const dv::value& root) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void foreach_file(
|
static inline void foreach_file(
|
||||||
const fs::path& dir, std::function<void(const fs::path&)> handler
|
const io::path& dir, std::function<void(const io::path&)> handler
|
||||||
) {
|
) {
|
||||||
if (fs::is_directory(dir)) {
|
if (!io::is_directory(dir)) {
|
||||||
for (const auto& entry : fs::directory_iterator(dir)) {
|
return;
|
||||||
const auto& path = entry.path();
|
}
|
||||||
if (fs::is_directory(path)) {
|
for (const auto& entry : fs::directory_iterator(io::resolve(dir))) {
|
||||||
continue;
|
io::path path = dir / entry.path().filename().u8string();
|
||||||
}
|
if (io::is_directory(path)) {
|
||||||
handler(path);
|
continue;
|
||||||
}
|
}
|
||||||
|
handler(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,11 +764,10 @@ void ContentLoader::load() {
|
|||||||
auto folder = pack->folder;
|
auto folder = pack->folder;
|
||||||
|
|
||||||
// Load world generators
|
// Load world generators
|
||||||
fs::path generatorsDir = folder / fs::u8path("generators");
|
io::path generatorsDir = folder / fs::u8path("generators");
|
||||||
foreach_file(generatorsDir, [this](const fs::path& file) {
|
foreach_file(generatorsDir, [this](const io::path& file) {
|
||||||
std::string name = file.stem().u8string();
|
std::string name = file.stem();
|
||||||
auto [packid, full, filename] =
|
auto [packid, full, filename] = create_unit_id(pack->id, name);
|
||||||
create_unit_id(pack->id, file.stem().u8string());
|
|
||||||
|
|
||||||
auto& def = builder.generators.create(full);
|
auto& def = builder.generators.create(full);
|
||||||
try {
|
try {
|
||||||
@ -776,8 +778,8 @@ void ContentLoader::load() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Load pack resources.json
|
// Load pack resources.json
|
||||||
fs::path resourcesFile = folder / fs::u8path("resources.json");
|
io::path resourcesFile = folder / "resources.json";
|
||||||
if (fs::exists(resourcesFile)) {
|
if (io::exists(resourcesFile)) {
|
||||||
auto resRoot = io::read_json(resourcesFile);
|
auto resRoot = io::read_json(resourcesFile);
|
||||||
for (const auto& [key, arr] : resRoot.asObject()) {
|
for (const auto& [key, arr] : resRoot.asObject()) {
|
||||||
if (auto resType = ResourceType_from(key)) {
|
if (auto resType = ResourceType_from(key)) {
|
||||||
@ -790,8 +792,8 @@ void ContentLoader::load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load pack resources aliases
|
// Load pack resources aliases
|
||||||
fs::path aliasesFile = folder / fs::u8path("resource-aliases.json");
|
io::path aliasesFile = folder / "resource-aliases.json";
|
||||||
if (fs::exists(aliasesFile)) {
|
if (io::exists(aliasesFile)) {
|
||||||
auto resRoot = io::read_json(aliasesFile);
|
auto resRoot = io::read_json(aliasesFile);
|
||||||
for (const auto& [key, arr] : resRoot.asObject()) {
|
for (const auto& [key, arr] : resRoot.asObject()) {
|
||||||
if (auto resType = ResourceType_from(key)) {
|
if (auto resType = ResourceType_from(key)) {
|
||||||
@ -804,32 +806,32 @@ void ContentLoader::load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load block materials
|
// Load block materials
|
||||||
fs::path materialsDir = folder / fs::u8path("block_materials");
|
io::path materialsDir = folder / "block_materials";
|
||||||
if (fs::is_directory(materialsDir)) {
|
if (io::is_directory(materialsDir)) {
|
||||||
for (const auto& entry : fs::directory_iterator(materialsDir)) {
|
for (const auto& entry : fs::directory_iterator(io::resolve(materialsDir))) {
|
||||||
const auto& file = entry.path();
|
io::path file = materialsDir / entry.path().filename().u8string();
|
||||||
auto [packid, full, filename] =
|
auto [packid, full, filename] =
|
||||||
create_unit_id(pack->id, file.stem().u8string());
|
create_unit_id(pack->id, file.stem());
|
||||||
loadBlockMaterial(
|
loadBlockMaterial(
|
||||||
builder.createBlockMaterial(full),
|
builder.createBlockMaterial(full),
|
||||||
materialsDir / fs::u8path(filename + ".json")
|
materialsDir / (filename + ".json")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load skeletons
|
// Load skeletons
|
||||||
fs::path skeletonsDir = folder / fs::u8path("skeletons");
|
io::path skeletonsDir = folder / fs::u8path("skeletons");
|
||||||
foreach_file(skeletonsDir, [this](const fs::path& file) {
|
foreach_file(skeletonsDir, [this](const io::path& file) {
|
||||||
std::string name = pack->id + ":" + file.stem().u8string();
|
std::string name = pack->id + ":" + file.stem();
|
||||||
std::string text = io::read_string(file);
|
std::string text = io::read_string(file);
|
||||||
builder.add(
|
builder.add(
|
||||||
rigging::SkeletonConfig::parse(text, file.u8string(), name)
|
rigging::SkeletonConfig::parse(text, file.string(), name)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Process content.json and load defined content units
|
// Process content.json and load defined content units
|
||||||
auto contentFile = pack->getContentFile();
|
auto contentFile = pack->getContentFile();
|
||||||
if (fs::exists(contentFile)) {
|
if (io::exists(contentFile)) {
|
||||||
loadContent(io::read_json(contentFile));
|
loadContent(io::read_json(contentFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -844,8 +846,8 @@ static void load_scripts(Content& content, ContentUnitDefs<T>& units) {
|
|||||||
const auto runtime = content.getPackRuntime(name.substr(0, pos));
|
const auto runtime = content.getPackRuntime(name.substr(0, pos));
|
||||||
const auto& pack = runtime->getInfo();
|
const auto& pack = runtime->getInfo();
|
||||||
const auto& folder = pack.folder;
|
const auto& folder = pack.folder;
|
||||||
auto scriptfile = folder / fs::path("scripts/" + def->scriptName + ".lua");
|
auto scriptfile = folder / ("scripts/" + def->scriptName + ".lua");
|
||||||
if (fs::is_regular_file(scriptfile)) {
|
if (io::is_regular_file(scriptfile)) {
|
||||||
scripting::load_content_script(
|
scripting::load_content_script(
|
||||||
runtime->getEnvironment(),
|
runtime->getEnvironment(),
|
||||||
name,
|
name,
|
||||||
@ -866,8 +868,8 @@ void ContentLoader::loadScripts(Content& content) {
|
|||||||
const auto& folder = pack.folder;
|
const auto& folder = pack.folder;
|
||||||
|
|
||||||
// Load main world script
|
// Load main world script
|
||||||
fs::path scriptFile = folder / fs::path("scripts/world.lua");
|
io::path scriptFile = folder / "scripts/world.lua";
|
||||||
if (fs::is_regular_file(scriptFile)) {
|
if (io::is_regular_file(scriptFile)) {
|
||||||
scripting::load_world_script(
|
scripting::load_world_script(
|
||||||
runtime->getEnvironment(),
|
runtime->getEnvironment(),
|
||||||
pack.id,
|
pack.id,
|
||||||
@ -877,13 +879,13 @@ void ContentLoader::loadScripts(Content& content) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Load entity components
|
// Load entity components
|
||||||
fs::path componentsDir = folder / fs::u8path("scripts/components");
|
io::path componentsDir = folder / fs::u8path("scripts/components");
|
||||||
foreach_file(componentsDir, [&pack](const fs::path& file) {
|
foreach_file(componentsDir, [&pack](const io::path& file) {
|
||||||
auto name = pack.id + ":" + file.stem().u8string();
|
auto name = pack.id + ":" + file.stem();
|
||||||
scripting::load_entity_component(
|
scripting::load_entity_component(
|
||||||
name,
|
name,
|
||||||
file,
|
file,
|
||||||
pack.id + ":scripts/components/" + file.filename().u8string()
|
pack.id + ":scripts/components/" + file.name()
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "io/io.hpp"
|
||||||
#include "content_fwd.hpp"
|
#include "content_fwd.hpp"
|
||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
class Block;
|
class Block;
|
||||||
struct BlockMaterial;
|
struct BlockMaterial;
|
||||||
struct ItemDef;
|
struct ItemDef;
|
||||||
@ -43,15 +41,15 @@ class ContentLoader {
|
|||||||
GeneratorDef& def, const std::string& full, const std::string& name
|
GeneratorDef& def, const std::string& full, const std::string& name
|
||||||
);
|
);
|
||||||
|
|
||||||
static void loadBlockMaterial(BlockMaterial& def, const fs::path& file);
|
static void loadBlockMaterial(BlockMaterial& def, const io::path& file);
|
||||||
void loadBlock(
|
void loadBlock(
|
||||||
Block& def, const std::string& name, const fs::path& file
|
Block& def, const std::string& name, const io::path& file
|
||||||
);
|
);
|
||||||
void loadItem(
|
void loadItem(
|
||||||
ItemDef& def, const std::string& name, const fs::path& file
|
ItemDef& def, const std::string& name, const io::path& file
|
||||||
);
|
);
|
||||||
void loadEntity(
|
void loadEntity(
|
||||||
EntityDef& def, const std::string& name, const fs::path& file
|
EntityDef& def, const std::string& name, const io::path& file
|
||||||
);
|
);
|
||||||
void loadResources(ResourceType type, const dv::value& list);
|
void loadResources(ResourceType type, const dv::value& list);
|
||||||
void loadResourceAliases(ResourceType type, const dv::value& aliases);
|
void loadResourceAliases(ResourceType type, const dv::value& aliases);
|
||||||
@ -66,7 +64,7 @@ public:
|
|||||||
|
|
||||||
// Refresh pack content.json
|
// Refresh pack content.json
|
||||||
static bool fixPackIndices(
|
static bool fixPackIndices(
|
||||||
const fs::path& folder,
|
const io::path& folder,
|
||||||
dv::value& indicesRoot,
|
dv::value& indicesRoot,
|
||||||
const std::string& contentSection
|
const std::string& contentSection
|
||||||
);
|
);
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
ContentPack ContentPack::createCore(const EnginePaths& paths) {
|
ContentPack ContentPack::createCore(const EnginePaths& paths) {
|
||||||
return ContentPack {
|
return ContentPack {
|
||||||
"core", "Core", ENGINE_VERSION_STRING, "", "", paths.getResourcesFolder(), "res:", {}
|
"core", "Core", ENGINE_VERSION_STRING, "", "", "res:", "res:", {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ const std::vector<std::string> ContentPack::RESERVED_NAMES = {
|
|||||||
"res", "abs", "local", "core", "user", "world", "none", "null"};
|
"res", "abs", "local", "core", "user", "world", "none", "null"};
|
||||||
|
|
||||||
contentpack_error::contentpack_error(
|
contentpack_error::contentpack_error(
|
||||||
std::string packId, fs::path folder, const std::string& message
|
std::string packId, io::path folder, const std::string& message
|
||||||
)
|
)
|
||||||
: std::runtime_error(message),
|
: std::runtime_error(message),
|
||||||
packId(std::move(packId)),
|
packId(std::move(packId)),
|
||||||
@ -33,19 +33,19 @@ contentpack_error::contentpack_error(
|
|||||||
std::string contentpack_error::getPackId() const {
|
std::string contentpack_error::getPackId() const {
|
||||||
return packId;
|
return packId;
|
||||||
}
|
}
|
||||||
fs::path contentpack_error::getFolder() const {
|
io::path contentpack_error::getFolder() const {
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path ContentPack::getContentFile() const {
|
io::path ContentPack::getContentFile() const {
|
||||||
return folder / fs::path(CONTENT_FILENAME);
|
return folder / CONTENT_FILENAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContentPack::is_pack(const fs::path& folder) {
|
bool ContentPack::is_pack(const io::path& folder) {
|
||||||
return fs::is_regular_file(folder / fs::path(PACKAGE_FILENAME));
|
return io::is_regular_file(folder / PACKAGE_FILENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkContentPackId(const std::string& id, const fs::path& folder) {
|
static void checkContentPackId(const std::string& id, const io::path& folder) {
|
||||||
if (id.length() < 2 || id.length() > 24)
|
if (id.length() < 2 || id.length() > 24)
|
||||||
throw contentpack_error(
|
throw contentpack_error(
|
||||||
id, folder, "content-pack id length is out of range [2, 24]"
|
id, folder, "content-pack id length is out of range [2, 24]"
|
||||||
@ -70,8 +70,8 @@ static void checkContentPackId(const std::string& id, const fs::path& folder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentPack ContentPack::read(const std::string& path, const fs::path& folder) {
|
ContentPack ContentPack::read(const std::string& path, const io::path& folder) {
|
||||||
auto root = io::read_json(folder / fs::path(PACKAGE_FILENAME));
|
auto root = io::read_json(folder / PACKAGE_FILENAME);
|
||||||
ContentPack pack;
|
ContentPack pack;
|
||||||
root.at("id").get(pack.id);
|
root.at("id").get(pack.id);
|
||||||
root.at("title").get(pack.title);
|
root.at("title").get(pack.title);
|
||||||
@ -124,21 +124,21 @@ ContentPack ContentPack::read(const std::string& path, const fs::path& folder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentPack::scanFolder(
|
void ContentPack::scanFolder(
|
||||||
const std::string& path, const fs::path& folder, std::vector<ContentPack>& packs
|
const std::string& path, const io::path& folder, std::vector<ContentPack>& packs
|
||||||
) {
|
) {
|
||||||
if (!fs::is_directory(folder)) {
|
if (!io::is_directory(folder)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto& entry : fs::directory_iterator(folder)) {
|
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||||
const fs::path& packFolder = entry.path();
|
io::path packFolder = folder / entry.path().filename().u8string();
|
||||||
if (!fs::is_directory(packFolder)) continue;
|
if (!io::is_directory(packFolder)) continue;
|
||||||
if (!is_pack(packFolder)) continue;
|
if (!is_pack(packFolder)) continue;
|
||||||
try {
|
try {
|
||||||
packs.push_back(
|
packs.push_back(
|
||||||
read(path + "/" + packFolder.filename().string(), packFolder)
|
read(path + "/" + packFolder.name(), packFolder)
|
||||||
);
|
);
|
||||||
} catch (const contentpack_error& err) {
|
} catch (const contentpack_error& err) {
|
||||||
std::cerr << "package.json error at " << err.getFolder().u8string();
|
std::cerr << "package.json error at " << err.getFolder().string();
|
||||||
std::cerr << ": " << err.what() << std::endl;
|
std::cerr << ": " << err.what() << std::endl;
|
||||||
} catch (const std::runtime_error& err) {
|
} catch (const std::runtime_error& err) {
|
||||||
std::cerr << err.what() << std::endl;
|
std::cerr << err.what() << std::endl;
|
||||||
@ -146,26 +146,26 @@ void ContentPack::scanFolder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> ContentPack::worldPacksList(const fs::path& folder) {
|
std::vector<std::string> ContentPack::worldPacksList(const io::path& folder) {
|
||||||
fs::path listfile = folder / fs::path("packs.list");
|
io::path listfile = folder / "packs.list";
|
||||||
if (!fs::is_regular_file(listfile)) {
|
if (!io::is_regular_file(listfile)) {
|
||||||
throw std::runtime_error("missing file 'packs.list'");
|
throw std::runtime_error("missing file 'packs.list'");
|
||||||
}
|
}
|
||||||
return io::read_list(listfile);
|
return io::read_list(listfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path ContentPack::findPack(
|
io::path ContentPack::findPack(
|
||||||
const EnginePaths* paths, const fs::path& worldDir, const std::string& name
|
const EnginePaths* paths, const io::path& worldDir, const std::string& name
|
||||||
) {
|
) {
|
||||||
fs::path folder = worldDir / fs::path("content") / fs::path(name);
|
io::path folder = worldDir / "content" / name;
|
||||||
if (fs::is_directory(folder)) {
|
if (io::is_directory(folder)) {
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
folder = paths->getUserFilesFolder() / fs::path("content") / fs::path(name);
|
folder = io::path("user:content") / name;
|
||||||
if (fs::is_directory(folder)) {
|
if (io::is_directory(folder)) {
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
return paths->getResourcesFolder() / fs::path("content") / fs::path(name);
|
return io::path("res:content") / name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentPackRuntime::ContentPackRuntime(ContentPack info, scriptenv env)
|
ContentPackRuntime::ContentPackRuntime(ContentPack info, scriptenv env)
|
||||||
|
|||||||
@ -1,27 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "content_fwd.hpp"
|
#include "content_fwd.hpp"
|
||||||
|
#include "io/io.hpp"
|
||||||
|
|
||||||
class EnginePaths;
|
class EnginePaths;
|
||||||
|
|
||||||
class contentpack_error : public std::runtime_error {
|
class contentpack_error : public std::runtime_error {
|
||||||
std::string packId;
|
std::string packId;
|
||||||
std::filesystem::path folder;
|
io::path folder;
|
||||||
public:
|
public:
|
||||||
contentpack_error(
|
contentpack_error(
|
||||||
std::string packId,
|
std::string packId,
|
||||||
std::filesystem::path folder,
|
io::path folder,
|
||||||
const std::string& message
|
const std::string& message
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string getPackId() const;
|
std::string getPackId() const;
|
||||||
std::filesystem::path getFolder() const;
|
io::path getFolder() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DependencyLevel {
|
enum class DependencyLevel {
|
||||||
@ -42,52 +42,52 @@ struct ContentPack {
|
|||||||
std::string version = "0.0";
|
std::string version = "0.0";
|
||||||
std::string creator = "";
|
std::string creator = "";
|
||||||
std::string description = "no description";
|
std::string description = "no description";
|
||||||
std::filesystem::path folder;
|
io::path folder;
|
||||||
std::string path;
|
std::string path;
|
||||||
std::vector<DependencyPack> dependencies;
|
std::vector<DependencyPack> dependencies;
|
||||||
std::string source = "";
|
std::string source = "";
|
||||||
|
|
||||||
std::filesystem::path getContentFile() const;
|
io::path getContentFile() const;
|
||||||
|
|
||||||
static inline const std::string PACKAGE_FILENAME = "package.json";
|
static inline const std::string PACKAGE_FILENAME = "package.json";
|
||||||
static inline const std::string CONTENT_FILENAME = "content.json";
|
static inline const std::string CONTENT_FILENAME = "content.json";
|
||||||
static inline const std::filesystem::path BLOCKS_FOLDER = "blocks";
|
static inline const io::path BLOCKS_FOLDER = "blocks";
|
||||||
static inline const std::filesystem::path ITEMS_FOLDER = "items";
|
static inline const io::path ITEMS_FOLDER = "items";
|
||||||
static inline const std::filesystem::path ENTITIES_FOLDER = "entities";
|
static inline const io::path ENTITIES_FOLDER = "entities";
|
||||||
static inline const std::filesystem::path GENERATORS_FOLDER = "generators";
|
static inline const io::path GENERATORS_FOLDER = "generators";
|
||||||
static const std::vector<std::string> RESERVED_NAMES;
|
static const std::vector<std::string> RESERVED_NAMES;
|
||||||
|
|
||||||
static bool is_pack(const std::filesystem::path& folder);
|
static bool is_pack(const io::path& folder);
|
||||||
static ContentPack read(
|
static ContentPack read(
|
||||||
const std::string& path, const std::filesystem::path& folder
|
const std::string& path, const io::path& folder
|
||||||
);
|
);
|
||||||
|
|
||||||
static void scanFolder(
|
static void scanFolder(
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
const std::filesystem::path& folder,
|
const io::path& folder,
|
||||||
std::vector<ContentPack>& packs
|
std::vector<ContentPack>& packs
|
||||||
);
|
);
|
||||||
|
|
||||||
static std::vector<std::string> worldPacksList(
|
static std::vector<std::string> worldPacksList(
|
||||||
const std::filesystem::path& folder
|
const io::path& folder
|
||||||
);
|
);
|
||||||
|
|
||||||
static std::filesystem::path findPack(
|
static io::path findPack(
|
||||||
const EnginePaths* paths,
|
const EnginePaths* paths,
|
||||||
const std::filesystem::path& worldDir,
|
const io::path& worldDir,
|
||||||
const std::string& name
|
const std::string& name
|
||||||
);
|
);
|
||||||
|
|
||||||
static ContentPack createCore(const EnginePaths&);
|
static ContentPack createCore(const EnginePaths&);
|
||||||
|
|
||||||
static inline std::filesystem::path getFolderFor(ContentType type) {
|
static inline io::path getFolderFor(ContentType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ContentType::BLOCK: return ContentPack::BLOCKS_FOLDER;
|
case ContentType::BLOCK: return ContentPack::BLOCKS_FOLDER;
|
||||||
case ContentType::ITEM: return ContentPack::ITEMS_FOLDER;
|
case ContentType::ITEM: return ContentPack::ITEMS_FOLDER;
|
||||||
case ContentType::ENTITY: return ContentPack::ENTITIES_FOLDER;
|
case ContentType::ENTITY: return ContentPack::ENTITIES_FOLDER;
|
||||||
case ContentType::GENERATOR: return ContentPack::GENERATORS_FOLDER;
|
case ContentType::GENERATOR: return ContentPack::GENERATORS_FOLDER;
|
||||||
case ContentType::NONE: return std::filesystem::u8path("");
|
case ContentType::NONE: return "";
|
||||||
default: return std::filesystem::u8path("");
|
default: return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -67,7 +67,7 @@ static void process_blocks_data(
|
|||||||
|
|
||||||
std::shared_ptr<ContentReport> ContentReport::create(
|
std::shared_ptr<ContentReport> ContentReport::create(
|
||||||
const std::shared_ptr<WorldFiles>& worldFiles,
|
const std::shared_ptr<WorldFiles>& worldFiles,
|
||||||
const fs::path& filename,
|
const io::path& filename,
|
||||||
const Content* content
|
const Content* content
|
||||||
) {
|
) {
|
||||||
auto worldInfo = worldFiles->readWorldInfo();
|
auto worldInfo = worldFiles->readWorldInfo();
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -10,10 +9,10 @@
|
|||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "Content.hpp"
|
#include "Content.hpp"
|
||||||
|
#include "io/io.hpp"
|
||||||
#include "data/StructLayout.hpp"
|
#include "data/StructLayout.hpp"
|
||||||
#include "world/files/world_regions_fwd.hpp"
|
#include "world/files/world_regions_fwd.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
enum class ContentIssueType {
|
enum class ContentIssueType {
|
||||||
REORDER,
|
REORDER,
|
||||||
@ -139,7 +138,7 @@ public:
|
|||||||
|
|
||||||
static std::shared_ptr<ContentReport> create(
|
static std::shared_ptr<ContentReport> create(
|
||||||
const std::shared_ptr<WorldFiles>& worldFiles,
|
const std::shared_ptr<WorldFiles>& worldFiles,
|
||||||
const fs::path& filename,
|
const io::path& filename,
|
||||||
const Content* content
|
const Content* content
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
PacksManager::PacksManager() = default;
|
PacksManager::PacksManager() = default;
|
||||||
|
|
||||||
void PacksManager::setSources(std::vector<std::pair<std::string, fs::path>> sources) {
|
void PacksManager::setSources(std::vector<std::pair<std::string, io::path>> sources) {
|
||||||
this->sources = std::move(sources);
|
this->sources = std::move(sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ std::vector<ContentPack> PacksManager::getAll(
|
|||||||
for (auto& name : names) {
|
for (auto& name : names) {
|
||||||
auto found = packs.find(name);
|
auto found = packs.find(name);
|
||||||
if (found == packs.end()) {
|
if (found == packs.end()) {
|
||||||
throw contentpack_error(name, fs::path(""), "pack not found");
|
throw contentpack_error(name, io::path(), "pack not found");
|
||||||
}
|
}
|
||||||
packsList.push_back(found->second);
|
packsList.push_back(found->second);
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ static bool resolve_dependencies(
|
|||||||
bool exists = found != packs.end();
|
bool exists = found != packs.end();
|
||||||
if (!exists && dep.level == DependencyLevel::required) {
|
if (!exists && dep.level == DependencyLevel::required) {
|
||||||
throw contentpack_error(
|
throw contentpack_error(
|
||||||
dep.id, fs::path(), "dependency of '" + pack->id + "'"
|
dep.id, io::path(), "dependency of '" + pack->id + "'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
@ -127,7 +127,7 @@ std::vector<std::string> PacksManager::assemble(
|
|||||||
for (auto& name : names) {
|
for (auto& name : names) {
|
||||||
auto found = packs.find(name);
|
auto found = packs.find(name);
|
||||||
if (found == packs.end()) {
|
if (found == packs.end()) {
|
||||||
throw contentpack_error(name, fs::path(""), "pack not found");
|
throw contentpack_error(name, io::path(), "pack not found");
|
||||||
}
|
}
|
||||||
queue.push(&found->second);
|
queue.push(&found->second);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "io/io.hpp"
|
||||||
#include "ContentPack.hpp"
|
#include "ContentPack.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
class PacksManager {
|
class PacksManager {
|
||||||
std::unordered_map<std::string, ContentPack> packs;
|
std::unordered_map<std::string, ContentPack> packs;
|
||||||
std::vector<std::pair<std::string, fs::path>> sources;
|
std::vector<std::pair<std::string, io::path>> sources;
|
||||||
public:
|
public:
|
||||||
PacksManager();
|
PacksManager();
|
||||||
|
|
||||||
/// @brief Set content packs sources (search folders)
|
/// @brief Set content packs sources (search folders)
|
||||||
void setSources(std::vector<std::pair<std::string, fs::path>> sources);
|
void setSources(std::vector<std::pair<std::string, io::path>> sources);
|
||||||
|
|
||||||
/// @brief Scan sources and collect all found packs excluding duplication.
|
/// @brief Scan sources and collect all found packs excluding duplication.
|
||||||
/// Scanning order depends on sources order
|
/// Scanning order depends on sources order
|
||||||
|
|||||||
@ -132,18 +132,18 @@ static VoxelStructureMeta load_structure_meta(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::unique_ptr<VoxelStructure>> load_structures(
|
static std::vector<std::unique_ptr<VoxelStructure>> load_structures(
|
||||||
const dv::value& map, const fs::path& filesFolder, const ResPaths& paths
|
const dv::value& map, const io::path& filesFolder, const ResPaths& paths
|
||||||
) {
|
) {
|
||||||
auto structuresDir = filesFolder / fs::path("fragments");
|
auto structuresDir = filesFolder / "fragments";
|
||||||
|
|
||||||
std::vector<std::unique_ptr<VoxelStructure>> structures;
|
std::vector<std::unique_ptr<VoxelStructure>> structures;
|
||||||
for (auto& [name, config] : map.asObject()) {
|
for (auto& [name, config] : map.asObject()) {
|
||||||
auto structFile = structuresDir / fs::u8path(name + ".vox");
|
auto structFile = structuresDir / (name + ".vox");
|
||||||
structFile = paths.find(structFile.u8string());
|
structFile = paths.find(structFile.string());
|
||||||
logger.debug() << "loading voxel fragment " << structFile.u8string();
|
logger.debug() << "loading voxel fragment " << structFile.string();
|
||||||
if (!fs::exists(structFile)) {
|
if (!io::exists(structFile)) {
|
||||||
throw std::runtime_error("structure file does not exist (" +
|
throw std::runtime_error("structure file does not exist (" +
|
||||||
structFile.u8string());
|
structFile.string());
|
||||||
}
|
}
|
||||||
auto fragment = std::make_unique<VoxelFragment>();
|
auto fragment = std::make_unique<VoxelFragment>();
|
||||||
fragment->deserialize(io::read_binary_json(structFile));
|
fragment->deserialize(io::read_binary_json(structFile));
|
||||||
@ -162,7 +162,7 @@ static std::vector<std::unique_ptr<VoxelStructure>> load_structures(
|
|||||||
static void load_structures(
|
static void load_structures(
|
||||||
GeneratorDef& def,
|
GeneratorDef& def,
|
||||||
const dv::value& map,
|
const dv::value& map,
|
||||||
const fs::path& filesFolder,
|
const io::path& filesFolder,
|
||||||
const ResPaths& paths
|
const ResPaths& paths
|
||||||
) {
|
) {
|
||||||
auto rawStructures = load_structures(map, filesFolder, paths);
|
auto rawStructures = load_structures(map, filesFolder, paths);
|
||||||
@ -178,9 +178,9 @@ static void load_structures(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const auto STRUCTURES_FILE = fs::u8path("structures.toml");
|
static inline const io::path STRUCTURES_FILE = "structures.toml";
|
||||||
static inline const auto BIOMES_FILE = fs::u8path("biomes.toml");
|
static inline const io::path BIOMES_FILE = "biomes.toml";
|
||||||
static inline const auto GENERATORS_DIR = fs::u8path("generators");
|
static inline const io::path GENERATORS_DIR = "generators";
|
||||||
|
|
||||||
static void load_biomes(GeneratorDef& def, const dv::value& root) {
|
static void load_biomes(GeneratorDef& def, const dv::value& root) {
|
||||||
for (const auto& [biomeName, biomeMap] : root.asObject()) {
|
for (const auto& [biomeName, biomeMap] : root.asObject()) {
|
||||||
@ -198,11 +198,11 @@ void ContentLoader::loadGenerator(
|
|||||||
) {
|
) {
|
||||||
auto packDir = pack->folder;
|
auto packDir = pack->folder;
|
||||||
auto generatorsDir = packDir / GENERATORS_DIR;
|
auto generatorsDir = packDir / GENERATORS_DIR;
|
||||||
auto generatorFile = generatorsDir / fs::u8path(name + ".toml");
|
auto generatorFile = generatorsDir / (name + ".toml");
|
||||||
if (!fs::exists(generatorFile)) {
|
if (!io::exists(generatorFile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto map = io::read_toml(generatorsDir / fs::u8path(name + ".toml"));
|
auto map = io::read_toml(generatorsDir / (name + ".toml"));
|
||||||
map.at("caption").get(def.caption);
|
map.at("caption").get(def.caption);
|
||||||
map.at("biome-parameters").get(def.biomeParameters);
|
map.at("biome-parameters").get(def.biomeParameters);
|
||||||
map.at("biome-bpd").get(def.biomesBPD);
|
map.at("biome-bpd").get(def.biomesBPD);
|
||||||
@ -233,15 +233,15 @@ void ContentLoader::loadGenerator(
|
|||||||
logger.warning() << "generator has heightmap-inputs but biomes-bpd "
|
logger.warning() << "generator has heightmap-inputs but biomes-bpd "
|
||||||
"is not equal to heights-bpd, generator will work slower!";
|
"is not equal to heights-bpd, generator will work slower!";
|
||||||
}
|
}
|
||||||
auto folder = generatorsDir / fs::u8path(name + ".files");
|
auto folder = generatorsDir / (name + ".files");
|
||||||
auto scriptFile = folder / fs::u8path("script.lua");
|
auto scriptFile = folder / "script.lua";
|
||||||
|
|
||||||
auto structuresFile = GENERATORS_DIR / fs::u8path(name + ".files") / STRUCTURES_FILE;
|
auto structuresFile = GENERATORS_DIR / (name + ".files") / STRUCTURES_FILE;
|
||||||
auto structuresMap = paths.readCombinedObject(structuresFile.u8string());
|
auto structuresMap = paths.readCombinedObject(structuresFile.string());
|
||||||
load_structures(def, structuresMap, structuresFile.parent_path(), paths);
|
load_structures(def, structuresMap, structuresFile.parent(), paths);
|
||||||
|
|
||||||
auto biomesFile = GENERATORS_DIR / fs::u8path(name + ".files") / BIOMES_FILE;
|
auto biomesFile = GENERATORS_DIR / (name + ".files") / BIOMES_FILE;
|
||||||
auto biomesMap = paths.readCombinedObject(biomesFile.u8string());
|
auto biomesMap = paths.readCombinedObject(biomesFile.string());
|
||||||
if (biomesMap.empty()) {
|
if (biomesMap.empty()) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"generator " + util::quote(def.name) +
|
"generator " + util::quote(def.name) +
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
|
|
||||||
// All in-game definitions (blocks, items, etc..)
|
// All in-game definitions (blocks, items, etc..)
|
||||||
void corecontent::setup(const EnginePaths& paths, ContentBuilder& builder) {
|
void corecontent::setup(ContentBuilder& builder) {
|
||||||
{
|
{
|
||||||
Block& block = builder.blocks.create(CORE_AIR);
|
Block& block = builder.blocks.create(CORE_AIR);
|
||||||
block.replaceable = true;
|
block.replaceable = true;
|
||||||
@ -28,10 +28,10 @@ void corecontent::setup(const EnginePaths& paths, ContentBuilder& builder) {
|
|||||||
item.iconType = ItemIconType::NONE;
|
item.iconType = ItemIconType::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bindsFile = paths.getResourcesFolder()/fs::path("bindings.toml");
|
auto bindsFile = "res:bindings.toml";
|
||||||
if (fs::is_regular_file(bindsFile)) {
|
if (io::is_regular_file(bindsFile)) {
|
||||||
Events::loadBindings(
|
Events::loadBindings(
|
||||||
bindsFile.u8string(), io::read_string(bindsFile), BindType::BIND
|
bindsFile, io::read_string(bindsFile), BindType::BIND
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,9 +28,8 @@ inline const std::string BIND_PLAYER_FAST_INTERACTOIN =
|
|||||||
"player.fast_interaction";
|
"player.fast_interaction";
|
||||||
inline const std::string BIND_HUD_INVENTORY = "hud.inventory";
|
inline const std::string BIND_HUD_INVENTORY = "hud.inventory";
|
||||||
|
|
||||||
class EnginePaths;
|
|
||||||
class ContentBuilder;
|
class ContentBuilder;
|
||||||
|
|
||||||
namespace corecontent {
|
namespace corecontent {
|
||||||
void setup(const EnginePaths& paths, ContentBuilder& builder);
|
void setup(ContentBuilder& builder);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,10 +52,10 @@ static debug::Logger logger("engine");
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static std::unique_ptr<ImageData> load_icon(const fs::path& resdir) {
|
static std::unique_ptr<ImageData> load_icon() {
|
||||||
try {
|
try {
|
||||||
auto file = resdir / fs::u8path("textures/misc/icon.png");
|
auto file = "res:textures/misc/icon.png";
|
||||||
if (fs::exists(file)) {
|
if (io::exists(file)) {
|
||||||
return imageio::read(file);
|
return imageio::read(file);
|
||||||
}
|
}
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
@ -101,7 +101,7 @@ void Engine::initialize(CoreParameters coreParameters) {
|
|||||||
throw initialize_error("could not initialize window");
|
throw initialize_error("could not initialize window");
|
||||||
}
|
}
|
||||||
time.set(Window::time());
|
time.set(Window::time());
|
||||||
if (auto icon = load_icon(resdir)) {
|
if (auto icon = load_icon()) {
|
||||||
icon->flipY();
|
icon->flipY();
|
||||||
Window::setIcon(icon.get());
|
Window::setIcon(icon.get());
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ void Engine::initialize(CoreParameters coreParameters) {
|
|||||||
if (langNotSet) {
|
if (langNotSet) {
|
||||||
settings.ui.language.set(langs::locale_by_envlocale(
|
settings.ui.language.set(langs::locale_by_envlocale(
|
||||||
platform::detect_locale(),
|
platform::detect_locale(),
|
||||||
paths.getResourcesFolder()
|
"res:"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
scripting::initialize(this);
|
scripting::initialize(this);
|
||||||
@ -128,12 +128,12 @@ void Engine::initialize(CoreParameters coreParameters) {
|
|||||||
keepAlive(settings.ui.language.observe([this](auto lang) {
|
keepAlive(settings.ui.language.observe([this](auto lang) {
|
||||||
setLanguage(lang);
|
setLanguage(lang);
|
||||||
}, true));
|
}, true));
|
||||||
basePacks = io::read_list(resdir/fs::path("config/builtins.list"));
|
basePacks = io::read_list("res:config/builtins.list");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadSettings() {
|
void Engine::loadSettings() {
|
||||||
fs::path settings_file = paths.getSettingsFile();
|
io::path settings_file = paths.getSettingsFile();
|
||||||
if (fs::is_regular_file(settings_file)) {
|
if (io::is_regular_file(settings_file)) {
|
||||||
logger.info() << "loading settings";
|
logger.info() << "loading settings";
|
||||||
std::string text = io::read_string(settings_file);
|
std::string text = io::read_string(settings_file);
|
||||||
try {
|
try {
|
||||||
@ -146,11 +146,11 @@ void Engine::loadSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadControls() {
|
void Engine::loadControls() {
|
||||||
fs::path controls_file = paths.getControlsFile();
|
io::path controls_file = paths.getControlsFile();
|
||||||
if (fs::is_regular_file(controls_file)) {
|
if (io::is_regular_file(controls_file)) {
|
||||||
logger.info() << "loading controls";
|
logger.info() << "loading controls";
|
||||||
std::string text = io::read_string(controls_file);
|
std::string text = io::read_string(controls_file);
|
||||||
Events::loadBindings(controls_file.u8string(), text, BindType::BIND);
|
Events::loadBindings(controls_file.string(), text, BindType::BIND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,9 +171,9 @@ void Engine::updateHotkeys() {
|
|||||||
void Engine::saveScreenshot() {
|
void Engine::saveScreenshot() {
|
||||||
auto image = Window::takeScreenshot();
|
auto image = Window::takeScreenshot();
|
||||||
image->flipY();
|
image->flipY();
|
||||||
fs::path filename = paths.getNewScreenshotFile("png");
|
io::path filename = paths.getNewScreenshotFile("png");
|
||||||
imageio::write(filename.string(), image.get());
|
imageio::write(filename.string(), image.get());
|
||||||
logger.info() << "saved screenshot as " << filename.u8string();
|
logger.info() << "saved screenshot as " << filename.string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::run() {
|
void Engine::run() {
|
||||||
@ -264,12 +264,12 @@ cmd::CommandsInterpreter* Engine::getCommandsInterpreter() {
|
|||||||
return interpreter.get();
|
return interpreter.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
PacksManager Engine::createPacksManager(const fs::path& worldFolder) {
|
PacksManager Engine::createPacksManager(const io::path& worldFolder) {
|
||||||
PacksManager manager;
|
PacksManager manager;
|
||||||
manager.setSources({
|
manager.setSources({
|
||||||
{"world:content", worldFolder.empty() ? worldFolder : worldFolder/fs::path("content")},
|
{"world:content", worldFolder.empty() ? worldFolder : worldFolder / "content"},
|
||||||
{"user:content", paths.getUserFilesFolder()/fs::path("content")},
|
{"user:content", "user:content"},
|
||||||
{"res:content", paths.getResourcesFolder()/fs::path("content")}
|
{"res:content", "res:content"}
|
||||||
});
|
});
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
@ -325,12 +325,12 @@ void Engine::loadAssets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_configs(const fs::path& root) {
|
static void load_configs(const io::path& root) {
|
||||||
auto configFolder = root/fs::path("config");
|
auto configFolder = root/io::path("config");
|
||||||
auto bindsFile = configFolder/fs::path("bindings.toml");
|
auto bindsFile = configFolder/io::path("bindings.toml");
|
||||||
if (fs::is_regular_file(bindsFile)) {
|
if (io::is_regular_file(bindsFile)) {
|
||||||
Events::loadBindings(
|
Events::loadBindings(
|
||||||
bindsFile.u8string(), io::read_string(bindsFile), BindType::BIND
|
bindsFile.string(), io::read_string(bindsFile), BindType::BIND
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,15 +338,13 @@ static void load_configs(const fs::path& root) {
|
|||||||
void Engine::loadContent() {
|
void Engine::loadContent() {
|
||||||
scripting::cleanup();
|
scripting::cleanup();
|
||||||
|
|
||||||
auto resdir = paths.getResourcesFolder();
|
|
||||||
|
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
for (auto& pack : contentPacks) {
|
for (auto& pack : contentPacks) {
|
||||||
names.push_back(pack.id);
|
names.push_back(pack.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentBuilder contentBuilder;
|
ContentBuilder contentBuilder;
|
||||||
corecontent::setup(paths, contentBuilder);
|
corecontent::setup(contentBuilder);
|
||||||
|
|
||||||
paths.setContentPacks(&contentPacks);
|
paths.setContentPacks(&contentPacks);
|
||||||
PacksManager manager = createPacksManager(paths.getCurrentWorldFolder());
|
PacksManager manager = createPacksManager(paths.getCurrentWorldFolder());
|
||||||
@ -363,7 +361,7 @@ void Engine::loadContent() {
|
|||||||
for (auto& pack : contentPacks) {
|
for (auto& pack : contentPacks) {
|
||||||
resRoots.push_back({pack.id, pack.folder});
|
resRoots.push_back({pack.id, pack.folder});
|
||||||
}
|
}
|
||||||
resPaths = std::make_unique<ResPaths>(resdir, resRoots);
|
resPaths = std::make_unique<ResPaths>("res:", resRoots);
|
||||||
|
|
||||||
// Load content
|
// Load content
|
||||||
{
|
{
|
||||||
@ -380,7 +378,7 @@ void Engine::loadContent() {
|
|||||||
|
|
||||||
ContentLoader::loadScripts(*content);
|
ContentLoader::loadScripts(*content);
|
||||||
|
|
||||||
langs::setup(resdir, langs::current->getId(), contentPacks);
|
langs::setup("res:", langs::current->getId(), contentPacks);
|
||||||
if (!isHeadless()) {
|
if (!isHeadless()) {
|
||||||
loadAssets();
|
loadAssets();
|
||||||
onAssetsLoaded();
|
onAssetsLoaded();
|
||||||
@ -389,23 +387,22 @@ void Engine::loadContent() {
|
|||||||
|
|
||||||
void Engine::resetContent() {
|
void Engine::resetContent() {
|
||||||
scripting::cleanup();
|
scripting::cleanup();
|
||||||
auto resdir = paths.getResourcesFolder();
|
|
||||||
std::vector<PathsRoot> resRoots;
|
std::vector<PathsRoot> resRoots;
|
||||||
{
|
{
|
||||||
auto pack = ContentPack::createCore(paths);
|
auto pack = ContentPack::createCore(paths);
|
||||||
resRoots.push_back({"core", pack.folder});
|
resRoots.push_back({"core", pack.folder});
|
||||||
load_configs(pack.folder);
|
load_configs(pack.folder);
|
||||||
}
|
}
|
||||||
auto manager = createPacksManager(fs::path());
|
auto manager = createPacksManager(io::path());
|
||||||
manager.scan();
|
manager.scan();
|
||||||
for (const auto& pack : manager.getAll(basePacks)) {
|
for (const auto& pack : manager.getAll(basePacks)) {
|
||||||
resRoots.push_back({pack.id, pack.folder});
|
resRoots.push_back({pack.id, pack.folder});
|
||||||
}
|
}
|
||||||
resPaths = std::make_unique<ResPaths>(resdir, resRoots);
|
resPaths = std::make_unique<ResPaths>("res:", resRoots);
|
||||||
contentPacks.clear();
|
contentPacks.clear();
|
||||||
content.reset();
|
content.reset();
|
||||||
|
|
||||||
langs::setup(resdir, langs::current->getId(), contentPacks);
|
langs::setup("res:", langs::current->getId(), contentPacks);
|
||||||
if (!isHeadless()) {
|
if (!isHeadless()) {
|
||||||
loadAssets();
|
loadAssets();
|
||||||
onAssetsLoaded();
|
onAssetsLoaded();
|
||||||
@ -414,15 +411,14 @@ void Engine::resetContent() {
|
|||||||
contentPacks = manager.getAll(basePacks);
|
contentPacks = manager.getAll(basePacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadWorldContent(const fs::path& folder) {
|
void Engine::loadWorldContent(const io::path& folder) {
|
||||||
contentPacks.clear();
|
contentPacks.clear();
|
||||||
auto packNames = ContentPack::worldPacksList(folder);
|
auto packNames = ContentPack::worldPacksList(folder);
|
||||||
PacksManager manager;
|
PacksManager manager;
|
||||||
manager.setSources(
|
manager.setSources(
|
||||||
{{"world:content",
|
{{"world:content", folder.empty() ? folder : folder / "content"},
|
||||||
folder.empty() ? folder : folder / fs::path("content")},
|
{"user:content", "user:content"},
|
||||||
{"user:content", paths.getUserFilesFolder() / fs::path("content")},
|
{"res:content", "res:content"}}
|
||||||
{"res:content", paths.getResourcesFolder() / fs::path("content")}}
|
|
||||||
);
|
);
|
||||||
manager.scan();
|
manager.scan();
|
||||||
contentPacks = manager.getAll(manager.assemble(packNames));
|
contentPacks = manager.getAll(manager.assemble(packNames));
|
||||||
@ -445,7 +441,7 @@ 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("res:", std::move(locale), contentPacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::onWorldOpen(std::unique_ptr<Level> level, int64_t localPlayer) {
|
void Engine::onWorldOpen(std::unique_ptr<Level> level, int64_t localPlayer) {
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
#include "PostRunnables.hpp"
|
#include "PostRunnables.hpp"
|
||||||
#include "Time.hpp"
|
#include "Time.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -48,8 +47,8 @@ public:
|
|||||||
struct CoreParameters {
|
struct CoreParameters {
|
||||||
bool headless = false;
|
bool headless = false;
|
||||||
bool testMode = false;
|
bool testMode = false;
|
||||||
std::filesystem::path resFolder {"res"};
|
std::filesystem::path resFolder = "res";
|
||||||
std::filesystem::path userFolder {"."};
|
std::filesystem::path userFolder = ".";
|
||||||
std::filesystem::path scriptFile;
|
std::filesystem::path scriptFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,7 +121,7 @@ public:
|
|||||||
/// @brief Collect world content-packs and load content
|
/// @brief Collect world content-packs and load content
|
||||||
/// @see loadContent
|
/// @see loadContent
|
||||||
/// @param folder world folder
|
/// @param folder world folder
|
||||||
void loadWorldContent(const fs::path& folder);
|
void loadWorldContent(const io::path& folder);
|
||||||
|
|
||||||
/// @brief Collect all available content-packs from res/content
|
/// @brief Collect all available content-packs from res/content
|
||||||
void loadAllPacks();
|
void loadAllPacks();
|
||||||
@ -172,7 +171,7 @@ public:
|
|||||||
EngineController* getController();
|
EngineController* getController();
|
||||||
cmd::CommandsInterpreter* getCommandsInterpreter();
|
cmd::CommandsInterpreter* getCommandsInterpreter();
|
||||||
|
|
||||||
PacksManager createPacksManager(const fs::path& worldFolder);
|
PacksManager createPacksManager(const io::path& worldFolder);
|
||||||
|
|
||||||
void setLevelConsumer(OnWorldOpen levelConsumer);
|
void setLevelConsumer(OnWorldOpen levelConsumer);
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,10 @@ void ServerMainloop::run() {
|
|||||||
setLevel(std::move(level));
|
setLevel(std::move(level));
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info() << "starting test " << coreParams.scriptFile;
|
logger.info() << "starting test " << coreParams.scriptFile.string();
|
||||||
auto process = scripting::start_coroutine(coreParams.scriptFile);
|
auto process = scripting::start_coroutine(
|
||||||
|
"script:" + coreParams.scriptFile.filename().u8string()
|
||||||
|
);
|
||||||
|
|
||||||
double targetDelta = 1.0 / static_cast<double>(TPS);
|
double targetDelta = 1.0 / static_cast<double>(TPS);
|
||||||
double delta = targetDelta;
|
double delta = targetDelta;
|
||||||
@ -76,7 +78,7 @@ void ServerMainloop::run() {
|
|||||||
void ServerMainloop::setLevel(std::unique_ptr<Level> level) {
|
void ServerMainloop::setLevel(std::unique_ptr<Level> level) {
|
||||||
if (level == nullptr) {
|
if (level == nullptr) {
|
||||||
controller->onWorldQuit();
|
controller->onWorldQuit();
|
||||||
engine.getPaths().setCurrentWorldFolder(fs::path());
|
engine.getPaths().setCurrentWorldFolder("");
|
||||||
controller = nullptr;
|
controller = nullptr;
|
||||||
} else {
|
} else {
|
||||||
controller = std::make_unique<LevelController>(
|
controller = std::make_unique<LevelController>(
|
||||||
|
|||||||
@ -56,22 +56,22 @@ scriptenv UiDocument::getEnvironment() const {
|
|||||||
std::unique_ptr<UiDocument> UiDocument::read(
|
std::unique_ptr<UiDocument> UiDocument::read(
|
||||||
const scriptenv& penv,
|
const scriptenv& penv,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
) {
|
) {
|
||||||
const std::string text = io::read_string(file);
|
const std::string text = io::read_string(file);
|
||||||
auto xmldoc = xml::parse(file.u8string(), text);
|
auto xmldoc = xml::parse(file.string(), text);
|
||||||
|
|
||||||
auto env = penv == nullptr
|
auto env = penv == nullptr
|
||||||
? scripting::create_doc_environment(scripting::get_root_environment(), name)
|
? scripting::create_doc_environment(scripting::get_root_environment(), name)
|
||||||
: scripting::create_doc_environment(penv, name);
|
: scripting::create_doc_environment(penv, name);
|
||||||
|
|
||||||
gui::UiXmlReader reader(env);
|
gui::UiXmlReader reader(env);
|
||||||
auto view = reader.readXML(file.u8string(), *xmldoc->getRoot());
|
auto view = reader.readXML(file.string(), *xmldoc->getRoot());
|
||||||
view->setId("root");
|
view->setId("root");
|
||||||
uidocscript script {};
|
uidocscript script {};
|
||||||
auto scriptFile = fs::path(file.u8string()+".lua");
|
auto scriptFile = io::path(file.string()+".lua");
|
||||||
if (fs::is_regular_file(scriptFile)) {
|
if (io::is_regular_file(scriptFile)) {
|
||||||
scripting::load_layout_script(
|
scripting::load_layout_script(
|
||||||
env, name, scriptFile, fileName + ".lua", script
|
env, name, scriptFile, fileName + ".lua", script
|
||||||
);
|
);
|
||||||
@ -80,8 +80,8 @@ std::unique_ptr<UiDocument> UiDocument::read(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<gui::UINode> UiDocument::readElement(
|
std::shared_ptr<gui::UINode> UiDocument::readElement(
|
||||||
const fs::path& file, const std::string& fileName
|
const io::path& file, const std::string& fileName
|
||||||
) {
|
) {
|
||||||
auto document = read(nullptr, file.filename().u8string(), file, fileName);
|
auto document = read(nullptr, file.name(), file, fileName);
|
||||||
return document->getRoot();
|
return document->getRoot();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,9 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <filesystem>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class UINode;
|
class UINode;
|
||||||
@ -48,10 +47,10 @@ public:
|
|||||||
static std::unique_ptr<UiDocument> read(
|
static std::unique_ptr<UiDocument> read(
|
||||||
const scriptenv& parent_env,
|
const scriptenv& parent_env,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
);
|
);
|
||||||
static std::shared_ptr<gui::UINode> readElement(
|
static std::shared_ptr<gui::UINode> readElement(
|
||||||
const fs::path& file, const std::string& fileName
|
const io::path& file, const std::string& fileName
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -69,8 +69,8 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void langs::loadLocalesInfo(const fs::path& resdir, std::string& fallback) {
|
void langs::loadLocalesInfo(const io::path& resdir, std::string& fallback) {
|
||||||
auto file = resdir/fs::u8path(langs::TEXTS_FOLDER)/fs::u8path("langs.json");
|
auto file = resdir / langs::TEXTS_FOLDER / "langs.json";
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
|
|
||||||
langs::locales_info.clear();
|
langs::locales_info.clear();
|
||||||
@ -94,7 +94,7 @@ void langs::loadLocalesInfo(const fs::path& resdir, std::string& fallback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string langs::locale_by_envlocale(const std::string& envlocale, const fs::path& resdir){
|
std::string langs::locale_by_envlocale(const std::string& envlocale, const io::path& resdir){
|
||||||
std::string fallback = FALLBACK_DEFAULT;
|
std::string fallback = FALLBACK_DEFAULT;
|
||||||
if (locales_info.size() == 0) {
|
if (locales_info.size() == 0) {
|
||||||
loadLocalesInfo(resdir, fallback);
|
loadLocalesInfo(resdir, fallback);
|
||||||
@ -115,21 +115,21 @@ std::string langs::locale_by_envlocale(const std::string& envlocale, const fs::p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void langs::load(const fs::path& resdir,
|
void langs::load(const io::path& resdir,
|
||||||
const std::string& locale,
|
const std::string& locale,
|
||||||
const std::vector<ContentPack>& packs,
|
const std::vector<ContentPack>& packs,
|
||||||
Lang& lang) {
|
Lang& lang) {
|
||||||
fs::path filename = fs::path(TEXTS_FOLDER)/fs::path(locale + LANG_FILE_EXT);
|
io::path filename = io::path(TEXTS_FOLDER) / (locale + LANG_FILE_EXT);
|
||||||
fs::path core_file = resdir/filename;
|
io::path core_file = resdir / filename;
|
||||||
|
|
||||||
if (fs::is_regular_file(core_file)) {
|
if (io::is_regular_file(core_file)) {
|
||||||
std::string text = io::read_string(core_file);
|
std::string text = io::read_string(core_file);
|
||||||
Reader reader(core_file.string(), text);
|
Reader reader(core_file.string(), text);
|
||||||
reader.read(lang, "");
|
reader.read(lang, "");
|
||||||
}
|
}
|
||||||
for (auto pack : packs) {
|
for (auto pack : packs) {
|
||||||
fs::path file = pack.folder/filename;
|
io::path file = pack.folder / filename;
|
||||||
if (fs::is_regular_file(file)) {
|
if (io::is_regular_file(file)) {
|
||||||
std::string text = io::read_string(file);
|
std::string text = io::read_string(file);
|
||||||
Reader reader(file.string(), text);
|
Reader reader(file.string(), text);
|
||||||
reader.read(lang, "");
|
reader.read(lang, "");
|
||||||
@ -137,7 +137,7 @@ void langs::load(const fs::path& resdir,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void langs::load(const fs::path& resdir,
|
void langs::load(const io::path& resdir,
|
||||||
const std::string& locale,
|
const std::string& locale,
|
||||||
const std::string& fallback,
|
const std::string& fallback,
|
||||||
const std::vector<ContentPack>& packs) {
|
const std::vector<ContentPack>& packs) {
|
||||||
@ -149,7 +149,7 @@ void langs::load(const fs::path& resdir,
|
|||||||
current = std::move(lang);
|
current = std::move(lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
void langs::setup(const fs::path& resdir,
|
void langs::setup(const io::path& resdir,
|
||||||
std::string locale,
|
std::string locale,
|
||||||
const std::vector<ContentPack>& packs) {
|
const std::vector<ContentPack>& packs) {
|
||||||
std::string fallback = langs::FALLBACK_DEFAULT;
|
std::string fallback = langs::FALLBACK_DEFAULT;
|
||||||
|
|||||||
@ -3,9 +3,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <filesystem>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
struct ContentPack;
|
struct ContentPack;
|
||||||
|
|
||||||
namespace langs {
|
namespace langs {
|
||||||
@ -44,17 +45,17 @@ namespace langs {
|
|||||||
extern std::unordered_map<std::string, LocaleInfo> locales_info;
|
extern std::unordered_map<std::string, LocaleInfo> locales_info;
|
||||||
|
|
||||||
extern void loadLocalesInfo(
|
extern void loadLocalesInfo(
|
||||||
const std::filesystem::path& resdir,
|
const io::path& resdir,
|
||||||
std::string& fallback);
|
std::string& fallback);
|
||||||
|
|
||||||
extern std::string locale_by_envlocale(const std::string& envlocale,
|
extern std::string locale_by_envlocale(const std::string& envlocale,
|
||||||
const std::filesystem::path& resdir);
|
const io::path& resdir);
|
||||||
|
|
||||||
extern void load(const std::filesystem::path& resdir,
|
extern void load(const io::path& resdir,
|
||||||
const std::string& locale,
|
const std::string& locale,
|
||||||
const std::vector<ContentPack>& packs,
|
const std::vector<ContentPack>& packs,
|
||||||
Lang& lang);
|
Lang& lang);
|
||||||
extern void load(const std::filesystem::path& resdir,
|
extern void load(const io::path& resdir,
|
||||||
const std::string& locale,
|
const std::string& locale,
|
||||||
const std::string& fallback,
|
const std::string& fallback,
|
||||||
const std::vector<ContentPack>& packs);
|
const std::vector<ContentPack>& packs);
|
||||||
@ -63,7 +64,7 @@ namespace langs {
|
|||||||
extern const std::wstring& get(const std::wstring& key,
|
extern const std::wstring& get(const std::wstring& key,
|
||||||
const std::wstring& context);
|
const std::wstring& context);
|
||||||
|
|
||||||
extern void setup(const std::filesystem::path& resdir,
|
extern void setup(const io::path& resdir,
|
||||||
std::string locale,
|
std::string locale,
|
||||||
const std::vector<ContentPack>& packs);
|
const std::vector<ContentPack>& packs);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,8 +105,8 @@ void LevelScreen::initializeContent() {
|
|||||||
|
|
||||||
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
||||||
const ContentPack& info = pack->getInfo();
|
const ContentPack& info = pack->getInfo();
|
||||||
fs::path scriptFile = info.folder/fs::path("scripts/hud.lua");
|
io::path scriptFile = info.folder / "scripts/hud.lua";
|
||||||
if (fs::is_regular_file(scriptFile)) {
|
if (io::is_regular_file(scriptFile)) {
|
||||||
scripting::load_hud_script(
|
scripting::load_hud_script(
|
||||||
pack->getEnvironment(),
|
pack->getEnvironment(),
|
||||||
info.id,
|
info.id,
|
||||||
@ -124,7 +124,7 @@ LevelScreen::~LevelScreen() {
|
|||||||
// unblock all bindings
|
// unblock all bindings
|
||||||
Events::enableBindings();
|
Events::enableBindings();
|
||||||
controller->onWorldQuit();
|
controller->onWorldQuit();
|
||||||
engine.getPaths().setCurrentWorldFolder(fs::path());
|
engine.getPaths().setCurrentWorldFolder("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelScreen::saveWorldPreview() {
|
void LevelScreen::saveWorldPreview() {
|
||||||
@ -147,7 +147,7 @@ void LevelScreen::saveWorldPreview() {
|
|||||||
worldRenderer->draw(ctx, camera, false, true, 0.0f, postProcessing.get());
|
worldRenderer->draw(ctx, camera, false, true, 0.0f, postProcessing.get());
|
||||||
auto image = postProcessing->toImage();
|
auto image = postProcessing->toImage();
|
||||||
image->flipY();
|
image->flipY();
|
||||||
imageio::write(paths.resolve("world:preview.png").u8string(), image.get());
|
imageio::write(paths.resolve("world:preview.png").string(), image.get());
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
logger.error() << err.what();
|
logger.error() << err.what();
|
||||||
}
|
}
|
||||||
|
|||||||
76
src/io/devices/Device.hpp
Normal file
76
src/io/devices/Device.hpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "../path.hpp"
|
||||||
|
|
||||||
|
namespace io {
|
||||||
|
class Device {
|
||||||
|
public:
|
||||||
|
virtual ~Device() = default;
|
||||||
|
|
||||||
|
virtual std::filesystem::path resolve(std::string_view path) = 0;
|
||||||
|
|
||||||
|
virtual void write(std::string_view path, const void* data, size_t size) = 0;
|
||||||
|
virtual void read(std::string_view path, void* data, size_t size) = 0;
|
||||||
|
|
||||||
|
virtual size_t size(std::string_view path) = 0;
|
||||||
|
|
||||||
|
virtual bool exists(std::string_view path) = 0;
|
||||||
|
virtual bool isdir(std::string_view path) = 0;
|
||||||
|
virtual bool isfile(std::string_view path) = 0;
|
||||||
|
virtual void mkdirs(std::string_view path) = 0;
|
||||||
|
virtual bool remove(std::string_view path) = 0;
|
||||||
|
virtual uint64_t removeAll(std::string_view path) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SubDevice : public Device {
|
||||||
|
public:
|
||||||
|
SubDevice(std::shared_ptr<Device> parent, const std::string& path)
|
||||||
|
: parent(std::move(parent)), root(path) {}
|
||||||
|
|
||||||
|
std::filesystem::path resolve(std::string_view path) override {
|
||||||
|
return parent->resolve((root / path).pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(std::string_view path, const void* data, size_t size) override {
|
||||||
|
parent->write((root / path).pathPart(), data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(std::string_view path, void* data, size_t size) override {
|
||||||
|
parent->read((root / path).pathPart(), data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size(std::string_view path) override {
|
||||||
|
return parent->size((root / path).pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool exists(std::string_view path) override {
|
||||||
|
return parent->exists((root / path).pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isdir(std::string_view path) override {
|
||||||
|
return parent->isdir((root / path).pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isfile(std::string_view path) override {
|
||||||
|
return parent->isfile((root / path).pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
void mkdirs(std::string_view path) override {
|
||||||
|
parent->mkdirs((root / path).pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(std::string_view path) override {
|
||||||
|
return parent->remove((root / path).pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t removeAll(std::string_view path) override {
|
||||||
|
return parent->removeAll((root / path).pathPart());
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Device> parent;
|
||||||
|
path root;
|
||||||
|
};
|
||||||
|
}
|
||||||
63
src/io/devices/StdfsDevice.cpp
Normal file
63
src/io/devices/StdfsDevice.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "StdfsDevice.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
using namespace io;
|
||||||
|
|
||||||
|
std::filesystem::path StdfsDevice::resolve(std::string_view path) {
|
||||||
|
return root / std::filesystem::u8path(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdfsDevice::write(std::string_view path, const void* data, size_t size) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
std::ofstream output(resolved, std::ios::binary);
|
||||||
|
if (!output.is_open()) {
|
||||||
|
throw std::runtime_error("could not to open file " + resolved.u8string());
|
||||||
|
}
|
||||||
|
output.write((const char*)data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdfsDevice::read(std::string_view path, void* data, size_t size) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
std::ifstream input(resolved, std::ios::binary);
|
||||||
|
if (!input.is_open()) {
|
||||||
|
throw std::runtime_error("could not to open file " + resolved.u8string());
|
||||||
|
}
|
||||||
|
input.read((char*)data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t StdfsDevice::size(std::string_view path) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
return std::filesystem::file_size(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StdfsDevice::exists(std::string_view path) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
return std::filesystem::exists(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StdfsDevice::isdir(std::string_view path) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
return std::filesystem::is_directory(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StdfsDevice::isfile(std::string_view path) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
return std::filesystem::is_regular_file(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdfsDevice::mkdirs(std::string_view path) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
std::filesystem::create_directories(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StdfsDevice::remove(std::string_view path) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
return std::filesystem::remove(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t StdfsDevice::removeAll(std::string_view path) {
|
||||||
|
auto resolved = resolve(path);
|
||||||
|
return std::filesystem::remove_all(resolved);
|
||||||
|
}
|
||||||
21
src/io/devices/StdfsDevice.hpp
Normal file
21
src/io/devices/StdfsDevice.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "Device.hpp"
|
||||||
|
|
||||||
|
namespace io {
|
||||||
|
class StdfsDevice : public Device {
|
||||||
|
public:
|
||||||
|
StdfsDevice(std::filesystem::path root) : root(std::move(root)) {}
|
||||||
|
|
||||||
|
std::filesystem::path resolve(std::string_view path) override;
|
||||||
|
void write(std::string_view path, const void* data, size_t size) override;
|
||||||
|
void read(std::string_view path, void* data, size_t size) override;
|
||||||
|
size_t size(std::string_view path) override;
|
||||||
|
bool exists(std::string_view path) override;
|
||||||
|
bool isdir(std::string_view path) override;
|
||||||
|
bool isfile(std::string_view path) override;
|
||||||
|
void mkdirs(std::string_view path) override;
|
||||||
|
bool remove(std::string_view path) override;
|
||||||
|
uint64_t removeAll(std::string_view path) override;
|
||||||
|
private:
|
||||||
|
std::filesystem::path root;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -9,9 +9,12 @@
|
|||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "io/devices/StdfsDevice.hpp"
|
||||||
#include "world/files/WorldFiles.hpp"
|
#include "world/files/WorldFiles.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static debug::Logger logger("engine-paths");
|
static debug::Logger logger("engine-paths");
|
||||||
|
|
||||||
static inline auto SCREENSHOTS_FOLDER = std::filesystem::u8path("screenshots");
|
static inline auto SCREENSHOTS_FOLDER = std::filesystem::u8path("screenshots");
|
||||||
@ -22,15 +25,16 @@ static inline auto EXPORT_FOLDER = std::filesystem::u8path("export");
|
|||||||
static inline auto CONTROLS_FILE = std::filesystem::u8path("controls.toml");
|
static inline auto CONTROLS_FILE = std::filesystem::u8path("controls.toml");
|
||||||
static inline auto SETTINGS_FILE = std::filesystem::u8path("settings.toml");
|
static inline auto SETTINGS_FILE = std::filesystem::u8path("settings.toml");
|
||||||
|
|
||||||
static std::filesystem::path toCanonic(std::filesystem::path path) {
|
static io::path toCanonic(io::path path) {
|
||||||
std::stack<std::string> parts;
|
std::stack<std::string> parts;
|
||||||
path = path.lexically_normal();
|
|
||||||
|
path = std::filesystem::u8path(path.string()).lexically_normal().string();
|
||||||
do {
|
do {
|
||||||
parts.push(path.filename().u8string());
|
parts.push(path.name());
|
||||||
path = path.parent_path();
|
path = path.parent();
|
||||||
} while (!path.empty());
|
} while (!path.empty());
|
||||||
|
|
||||||
path = fs::u8path("");
|
path = "";
|
||||||
|
|
||||||
while (!parts.empty()) {
|
while (!parts.empty()) {
|
||||||
const std::string part = parts.top();
|
const std::string part = parts.top();
|
||||||
@ -48,44 +52,47 @@ static std::filesystem::path toCanonic(std::filesystem::path path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EnginePaths::prepare() {
|
void EnginePaths::prepare() {
|
||||||
if (!fs::is_directory(resourcesFolder)) {
|
io::set_device("res", std::make_shared<io::StdfsDevice>(resourcesFolder));
|
||||||
|
io::set_device("user", std::make_shared<io::StdfsDevice>(userFilesFolder));
|
||||||
|
|
||||||
|
if (!io::is_directory("res:")) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
resourcesFolder.u8string() + " is not a directory"
|
resourcesFolder.string() + " is not a directory"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!fs::is_directory(userFilesFolder)) {
|
if (!io::is_directory("user:")) {
|
||||||
fs::create_directories(userFilesFolder);
|
io::create_directories("user:");
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info() << "resources folder: " << fs::canonical(resourcesFolder).u8string();
|
logger.info() << "resources folder: " << fs::canonical(resourcesFolder).u8string();
|
||||||
logger.info() << "user files folder: " << fs::canonical(userFilesFolder).u8string();
|
logger.info() << "user files folder: " << fs::canonical(userFilesFolder).u8string();
|
||||||
|
|
||||||
auto contentFolder = userFilesFolder / CONTENT_FOLDER;
|
auto contentFolder = io::path("user:") / CONTENT_FOLDER;
|
||||||
if (!fs::is_directory(contentFolder)) {
|
if (!io::is_directory(contentFolder)) {
|
||||||
fs::create_directories(contentFolder);
|
io::create_directories(contentFolder);
|
||||||
}
|
}
|
||||||
auto exportFolder = userFilesFolder / EXPORT_FOLDER;
|
auto exportFolder = io::path("user:") / EXPORT_FOLDER;
|
||||||
if (!fs::is_directory(exportFolder)) {
|
if (!io::is_directory(exportFolder)) {
|
||||||
fs::create_directories(exportFolder);
|
io::create_directories(exportFolder);
|
||||||
}
|
}
|
||||||
auto configFolder = userFilesFolder / CONFIG_FOLDER;
|
auto configFolder = io::path("user:") / CONFIG_FOLDER;
|
||||||
if (!fs::is_directory(configFolder)) {
|
if (!io::is_directory(configFolder)) {
|
||||||
fs::create_directories(configFolder);
|
io::create_directories(configFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getUserFilesFolder() const {
|
const std::filesystem::path& EnginePaths::getUserFilesFolder() const {
|
||||||
return userFilesFolder;
|
return userFilesFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getResourcesFolder() const {
|
const std::filesystem::path& EnginePaths::getResourcesFolder() const {
|
||||||
return resourcesFolder;
|
return resourcesFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getNewScreenshotFile(const std::string& ext) {
|
io::path EnginePaths::getNewScreenshotFile(const std::string& ext) {
|
||||||
auto folder = userFilesFolder / SCREENSHOTS_FOLDER;
|
auto folder = io::path("user:") / SCREENSHOTS_FOLDER;
|
||||||
if (!fs::is_directory(folder)) {
|
if (!io::is_directory(folder)) {
|
||||||
fs::create_directory(folder);
|
io::create_directories(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto t = std::time(nullptr);
|
auto t = std::time(nullptr);
|
||||||
@ -96,55 +103,55 @@ std::filesystem::path EnginePaths::getNewScreenshotFile(const std::string& ext)
|
|||||||
ss << std::put_time(&tm, format);
|
ss << std::put_time(&tm, format);
|
||||||
std::string datetimestr = ss.str();
|
std::string datetimestr = ss.str();
|
||||||
|
|
||||||
auto filename = folder / fs::u8path("screenshot-" + datetimestr + "." + ext);
|
auto file = folder / ("screenshot-" + datetimestr + "." + ext);
|
||||||
uint index = 0;
|
uint index = 0;
|
||||||
while (fs::exists(filename)) {
|
while (io::exists(file)) {
|
||||||
filename = folder / fs::u8path(
|
file = folder / fs::u8path(
|
||||||
"screenshot-" + datetimestr + "-" +
|
"screenshot-" + datetimestr + "-" +
|
||||||
std::to_string(index) + "." + ext
|
std::to_string(index) + "." + ext
|
||||||
);
|
);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
return filename;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getWorldsFolder() const {
|
io::path EnginePaths::getWorldsFolder() const {
|
||||||
return userFilesFolder / WORLDS_FOLDER;
|
return io::path("user:") / WORLDS_FOLDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getConfigFolder() const {
|
io::path EnginePaths::getConfigFolder() const {
|
||||||
return userFilesFolder / CONFIG_FOLDER;
|
return io::path("user:") / CONFIG_FOLDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getCurrentWorldFolder() {
|
io::path EnginePaths::getCurrentWorldFolder() {
|
||||||
return currentWorldFolder;
|
return currentWorldFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getWorldFolderByName(const std::string& name) {
|
io::path EnginePaths::getWorldFolderByName(const std::string& name) {
|
||||||
return getWorldsFolder() / std::filesystem::path(name);
|
return getWorldsFolder() / std::filesystem::path(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getControlsFile() const {
|
io::path EnginePaths::getControlsFile() const {
|
||||||
return userFilesFolder / CONTROLS_FILE;
|
return io::path("user:") / CONTROLS_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::getSettingsFile() const {
|
io::path EnginePaths::getSettingsFile() const {
|
||||||
return userFilesFolder / SETTINGS_FILE;
|
return io::path("user:") / SETTINGS_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::filesystem::path> EnginePaths::scanForWorlds() const {
|
std::vector<io::path> EnginePaths::scanForWorlds() const {
|
||||||
std::vector<std::filesystem::path> folders;
|
std::vector<io::path> folders;
|
||||||
|
|
||||||
auto folder = getWorldsFolder();
|
auto folder = getWorldsFolder();
|
||||||
if (!fs::is_directory(folder)) return folders;
|
if (!io::is_directory(folder)) return folders;
|
||||||
|
|
||||||
for (const auto& entry : fs::directory_iterator(folder)) {
|
for (const auto& entry : std::filesystem::directory_iterator(io::resolve(folder))) {
|
||||||
if (!entry.is_directory()) {
|
if (!entry.is_directory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto& worldFolder = entry.path();
|
io::path worldFolder = folder / entry.path().filename().u8string();
|
||||||
auto worldFile = worldFolder / fs::u8path(WorldFiles::WORLD_FILE);
|
auto worldFile = worldFolder / WorldFiles::WORLD_FILE;
|
||||||
if (!fs::is_regular_file(worldFile)) {
|
if (!io::is_regular_file(worldFile)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
folders.push_back(worldFolder);
|
folders.push_back(worldFolder);
|
||||||
@ -152,10 +159,11 @@ std::vector<std::filesystem::path> EnginePaths::scanForWorlds() const {
|
|||||||
std::sort(
|
std::sort(
|
||||||
folders.begin(),
|
folders.begin(),
|
||||||
folders.end(),
|
folders.end(),
|
||||||
[](std::filesystem::path a, std::filesystem::path b) {
|
[](io::path a, io::path b) {
|
||||||
a = a / fs::u8path(WorldFiles::WORLD_FILE);
|
a = a / WorldFiles::WORLD_FILE;
|
||||||
b = b / fs::u8path(WorldFiles::WORLD_FILE);
|
b = b / WorldFiles::WORLD_FILE;
|
||||||
return fs::last_write_time(a) > fs::last_write_time(b);
|
return fs::last_write_time(io::resolve(a)) >
|
||||||
|
fs::last_write_time(io::resolve(b));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return folders;
|
return folders;
|
||||||
@ -170,11 +178,13 @@ void EnginePaths::setResourcesFolder(std::filesystem::path folder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EnginePaths::setScriptFolder(std::filesystem::path folder) {
|
void EnginePaths::setScriptFolder(std::filesystem::path folder) {
|
||||||
|
io::set_device("script", std::make_shared<io::StdfsDevice>(folder));
|
||||||
this->scriptFolder = std::move(folder);
|
this->scriptFolder = std::move(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnginePaths::setCurrentWorldFolder(std::filesystem::path folder) {
|
void EnginePaths::setCurrentWorldFolder(io::path folder) {
|
||||||
this->currentWorldFolder = std::move(folder);
|
this->currentWorldFolder = std::move(folder);
|
||||||
|
io::create_subdevice("world", "user", currentWorldFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnginePaths::setContentPacks(std::vector<ContentPack>* contentPacks) {
|
void EnginePaths::setContentPacks(std::vector<ContentPack>* contentPacks) {
|
||||||
@ -191,65 +201,64 @@ std::tuple<std::string, std::string> EnginePaths::parsePath(std::string_view pat
|
|||||||
return {prefix, filename};
|
return {prefix, filename};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path EnginePaths::resolve(
|
// TODO: remove
|
||||||
|
io::path EnginePaths::resolve(
|
||||||
const std::string& path, bool throwErr
|
const std::string& path, bool throwErr
|
||||||
) const {
|
) const {
|
||||||
auto [prefix, filename] = EnginePaths::parsePath(path);
|
auto [prefix, filename] = EnginePaths::parsePath(path);
|
||||||
if (prefix.empty()) {
|
if (prefix.empty()) {
|
||||||
throw files_access_error("no entry point specified");
|
throw files_access_error("no entry point specified");
|
||||||
}
|
}
|
||||||
filename = toCanonic(fs::u8path(filename)).u8string();
|
filename = toCanonic(filename).string();
|
||||||
|
|
||||||
if (prefix == "res" || prefix == "core") {
|
if (prefix == "core") {
|
||||||
return resourcesFolder / fs::u8path(filename);
|
return io::path("res:") / filename;
|
||||||
}
|
}
|
||||||
if (prefix == "user") {
|
|
||||||
return userFilesFolder / fs::u8path(filename);
|
if (prefix == "res" || prefix == "user" || prefix == "script") {
|
||||||
|
return prefix + ":" + filename;
|
||||||
}
|
}
|
||||||
if (prefix == "config") {
|
if (prefix == "config") {
|
||||||
return getConfigFolder() / fs::u8path(filename);
|
return getConfigFolder() / filename;
|
||||||
}
|
}
|
||||||
if (prefix == "world") {
|
if (prefix == "world") {
|
||||||
return currentWorldFolder / fs::u8path(filename);
|
return currentWorldFolder / filename;
|
||||||
}
|
}
|
||||||
if (prefix == "export") {
|
if (prefix == "export") {
|
||||||
return userFilesFolder / EXPORT_FOLDER / fs::u8path(filename);
|
return io::path("user:") / EXPORT_FOLDER / filename;
|
||||||
}
|
|
||||||
if (prefix == "script" && scriptFolder) {
|
|
||||||
return scriptFolder.value() / fs::u8path(filename);
|
|
||||||
}
|
}
|
||||||
if (contentPacks) {
|
if (contentPacks) {
|
||||||
for (auto& pack : *contentPacks) {
|
for (auto& pack : *contentPacks) {
|
||||||
if (pack.id == prefix) {
|
if (pack.id == prefix) {
|
||||||
return pack.folder / fs::u8path(filename);
|
return pack.folder / filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (throwErr) {
|
if (throwErr) {
|
||||||
throw files_access_error("unknown entry point '" + prefix + "'");
|
throw files_access_error("unknown entry point '" + prefix + "'");
|
||||||
}
|
}
|
||||||
return std::filesystem::path(filename);
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResPaths::ResPaths(std::filesystem::path mainRoot, std::vector<PathsRoot> roots)
|
ResPaths::ResPaths(io::path mainRoot, std::vector<PathsRoot> roots)
|
||||||
: mainRoot(std::move(mainRoot)), roots(std::move(roots)) {
|
: mainRoot(std::move(mainRoot)), roots(std::move(roots)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path ResPaths::find(const std::string& filename) const {
|
io::path ResPaths::find(const std::string& filename) const {
|
||||||
for (int i = roots.size() - 1; i >= 0; i--) {
|
for (int i = roots.size() - 1; i >= 0; i--) {
|
||||||
auto& root = roots[i];
|
auto& root = roots[i];
|
||||||
auto file = root.path / fs::u8path(filename);
|
auto file = root.path / filename;
|
||||||
if (fs::exists(file)) {
|
if (io::exists(file)) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mainRoot / fs::u8path(filename);
|
return mainRoot / filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ResPaths::findRaw(const std::string& filename) const {
|
std::string ResPaths::findRaw(const std::string& filename) const {
|
||||||
for (int i = roots.size() - 1; i >= 0; i--) {
|
for (int i = roots.size() - 1; i >= 0; i--) {
|
||||||
auto& root = roots[i];
|
auto& root = roots[i];
|
||||||
if (fs::exists(root.path / std::filesystem::path(filename))) {
|
if (io::exists(root.path / filename)) {
|
||||||
return root.name + ":" + filename;
|
return root.name + ":" + filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,8 +270,8 @@ std::vector<std::string> ResPaths::listdirRaw(const std::string& folderName) con
|
|||||||
for (int i = roots.size() - 1; i >= 0; i--) {
|
for (int i = roots.size() - 1; i >= 0; i--) {
|
||||||
auto& root = roots[i];
|
auto& root = roots[i];
|
||||||
auto folder = root.path / fs::u8path(folderName);
|
auto folder = root.path / fs::u8path(folderName);
|
||||||
if (!fs::is_directory(folder)) continue;
|
if (!io::is_directory(folder)) continue;
|
||||||
for (const auto& entry : fs::directory_iterator(folder)) {
|
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||||
auto name = entry.path().filename().u8string();
|
auto name = entry.path().filename().u8string();
|
||||||
entries.emplace_back(root.name + ":" + folderName + "/" + name);
|
entries.emplace_back(root.name + ":" + folderName + "/" + name);
|
||||||
}
|
}
|
||||||
@ -270,16 +279,16 @@ std::vector<std::string> ResPaths::listdirRaw(const std::string& folderName) con
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::filesystem::path> ResPaths::listdir(
|
std::vector<io::path> ResPaths::listdir(
|
||||||
const std::string& folderName
|
const std::string& folderName
|
||||||
) const {
|
) const {
|
||||||
std::vector<std::filesystem::path> entries;
|
std::vector<io::path> entries;
|
||||||
for (int i = roots.size() - 1; i >= 0; i--) {
|
for (int i = roots.size() - 1; i >= 0; i--) {
|
||||||
auto& root = roots[i];
|
auto& root = roots[i];
|
||||||
std::filesystem::path folder = root.path / fs::u8path(folderName);
|
io::path folder = root.path / folderName;
|
||||||
if (!fs::is_directory(folder)) continue;
|
if (!io::is_directory(folder)) continue;
|
||||||
for (const auto& entry : fs::directory_iterator(folder)) {
|
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||||
entries.push_back(entry.path());
|
entries.push_back(folder / entry.path().filename().u8string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return entries;
|
return entries;
|
||||||
@ -288,8 +297,8 @@ std::vector<std::filesystem::path> ResPaths::listdir(
|
|||||||
dv::value ResPaths::readCombinedList(const std::string& filename) const {
|
dv::value ResPaths::readCombinedList(const std::string& filename) const {
|
||||||
dv::value list = dv::list();
|
dv::value list = dv::list();
|
||||||
for (const auto& root : roots) {
|
for (const auto& root : roots) {
|
||||||
auto path = root.path / fs::u8path(filename);
|
auto path = root.path / filename;
|
||||||
if (!fs::exists(path)) {
|
if (!io::exists(path)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -313,8 +322,8 @@ dv::value ResPaths::readCombinedList(const std::string& filename) const {
|
|||||||
dv::value ResPaths::readCombinedObject(const std::string& filename) const {
|
dv::value ResPaths::readCombinedObject(const std::string& filename) const {
|
||||||
dv::value object = dv::object();
|
dv::value object = dv::object();
|
||||||
for (const auto& root : roots) {
|
for (const auto& root : roots) {
|
||||||
auto path = root.path / fs::u8path(filename);
|
auto path = root.path / filename;
|
||||||
if (!fs::exists(path)) {
|
if (!io::exists(path)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -335,6 +344,6 @@ dv::value ResPaths::readCombinedObject(const std::string& filename) const {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::filesystem::path& ResPaths::getMainRoot() const {
|
const io::path& ResPaths::getMainRoot() const {
|
||||||
return mainRoot;
|
return mainRoot;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "io.hpp"
|
||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
#include "content/ContentPack.hpp"
|
#include "content/ContentPack.hpp"
|
||||||
|
|
||||||
|
|
||||||
class files_access_error : public std::runtime_error {
|
class files_access_error : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
files_access_error(const std::string& msg) : std::runtime_error(msg) {
|
files_access_error(const std::string& msg) : std::runtime_error(msg) {
|
||||||
@ -22,29 +21,29 @@ public:
|
|||||||
void prepare();
|
void prepare();
|
||||||
|
|
||||||
void setUserFilesFolder(std::filesystem::path folder);
|
void setUserFilesFolder(std::filesystem::path folder);
|
||||||
std::filesystem::path getUserFilesFolder() const;
|
const std::filesystem::path& getUserFilesFolder() const;
|
||||||
|
|
||||||
void setResourcesFolder(std::filesystem::path folder);
|
void setResourcesFolder(std::filesystem::path folder);
|
||||||
std::filesystem::path getResourcesFolder() const;
|
const std::filesystem::path& getResourcesFolder() const;
|
||||||
|
|
||||||
void setScriptFolder(std::filesystem::path folder);
|
void setScriptFolder(std::filesystem::path folder);
|
||||||
|
|
||||||
std::filesystem::path getWorldFolderByName(const std::string& name);
|
io::path getWorldFolderByName(const std::string& name);
|
||||||
std::filesystem::path getWorldsFolder() const;
|
io::path getWorldsFolder() const;
|
||||||
std::filesystem::path getConfigFolder() const;
|
io::path getConfigFolder() const;
|
||||||
|
|
||||||
void setCurrentWorldFolder(std::filesystem::path folder);
|
void setCurrentWorldFolder(io::path folder);
|
||||||
std::filesystem::path getCurrentWorldFolder();
|
io::path getCurrentWorldFolder();
|
||||||
|
|
||||||
std::filesystem::path getNewScreenshotFile(const std::string& ext);
|
io::path getNewScreenshotFile(const std::string& ext);
|
||||||
std::filesystem::path getControlsFile() const;
|
io::path getControlsFile() const;
|
||||||
std::filesystem::path getSettingsFile() const;
|
io::path getSettingsFile() const;
|
||||||
|
|
||||||
void setContentPacks(std::vector<ContentPack>* contentPacks);
|
void setContentPacks(std::vector<ContentPack>* contentPacks);
|
||||||
|
|
||||||
std::vector<std::filesystem::path> scanForWorlds() const;
|
std::vector<io::path> scanForWorlds() const;
|
||||||
|
|
||||||
std::filesystem::path resolve(const std::string& path, bool throwErr = true) const;
|
io::path resolve(const std::string& path, bool throwErr = true) const;
|
||||||
|
|
||||||
static std::tuple<std::string, std::string> parsePath(std::string_view view);
|
static std::tuple<std::string, std::string> parsePath(std::string_view view);
|
||||||
|
|
||||||
@ -53,23 +52,23 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::filesystem::path userFilesFolder {"."};
|
std::filesystem::path userFilesFolder {"."};
|
||||||
std::filesystem::path resourcesFolder {"res"};
|
std::filesystem::path resourcesFolder {"res"};
|
||||||
std::filesystem::path currentWorldFolder;
|
io::path currentWorldFolder;
|
||||||
std::optional<std::filesystem::path> scriptFolder;
|
std::optional<std::filesystem::path> scriptFolder;
|
||||||
std::vector<ContentPack>* contentPacks = nullptr;
|
std::vector<ContentPack>* contentPacks = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PathsRoot {
|
struct PathsRoot {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::filesystem::path path;
|
io::path path;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResPaths {
|
class ResPaths {
|
||||||
public:
|
public:
|
||||||
ResPaths(std::filesystem::path mainRoot, std::vector<PathsRoot> roots);
|
ResPaths(io::path mainRoot, std::vector<PathsRoot> roots);
|
||||||
|
|
||||||
std::filesystem::path find(const std::string& filename) const;
|
io::path find(const std::string& filename) const;
|
||||||
std::string findRaw(const std::string& filename) const;
|
std::string findRaw(const std::string& filename) const;
|
||||||
std::vector<std::filesystem::path> listdir(const std::string& folder) const;
|
std::vector<io::path> listdir(const std::string& folder) const;
|
||||||
std::vector<std::string> listdirRaw(const std::string& folder) const;
|
std::vector<std::string> listdirRaw(const std::string& folder) const;
|
||||||
|
|
||||||
/// @brief Read all found list versions from all packs and combine into a
|
/// @brief Read all found list versions from all packs and combine into a
|
||||||
@ -79,9 +78,9 @@ public:
|
|||||||
|
|
||||||
dv::value readCombinedObject(const std::string& file) const;
|
dv::value readCombinedObject(const std::string& file) const;
|
||||||
|
|
||||||
const std::filesystem::path& getMainRoot() const;
|
const io::path& getMainRoot() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path mainRoot;
|
io::path mainRoot;
|
||||||
std::vector<PathsRoot> roots;
|
std::vector<PathsRoot> roots;
|
||||||
};
|
};
|
||||||
|
|||||||
5
src/io/fwd.hpp
Normal file
5
src/io/fwd.hpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace io {
|
||||||
|
class path;
|
||||||
|
}
|
||||||
214
src/io/io.cpp
214
src/io/io.cpp
@ -1,7 +1,7 @@
|
|||||||
#include "io.hpp"
|
#include "io.hpp"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -13,10 +13,44 @@
|
|||||||
#include "coders/toml.hpp"
|
#include "coders/toml.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
|
|
||||||
|
#include "devices/Device.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
io::rafile::rafile(const fs::path& filename)
|
static std::map<std::string, std::shared_ptr<io::Device>> devices;
|
||||||
: file(filename, std::ios::binary | std::ios::ate) {
|
|
||||||
|
void io::set_device(const std::string& name, std::shared_ptr<io::Device> device) {
|
||||||
|
devices[name] = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<io::Device> io::get_device(const std::string& name) {
|
||||||
|
const auto& found = devices.find(name);
|
||||||
|
if (found == devices.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
io::Device& io::require_device(const std::string& name) {
|
||||||
|
auto device = get_device(name);
|
||||||
|
if (!device) {
|
||||||
|
throw std::runtime_error("io-device not found: " + name);
|
||||||
|
}
|
||||||
|
return *device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void io::create_subdevice(
|
||||||
|
const std::string& name, const std::string& parent, const io::path& root
|
||||||
|
) {
|
||||||
|
auto parentDevice = get_device(parent);
|
||||||
|
if (!parentDevice) {
|
||||||
|
throw std::runtime_error("parent device not found for entry-point: " + parent);
|
||||||
|
}
|
||||||
|
set_device(name, std::make_shared<io::SubDevice>(parentDevice, root.pathPart()));
|
||||||
|
}
|
||||||
|
|
||||||
|
io::rafile::rafile(const io::path& filename)
|
||||||
|
: file(io::resolve(filename), std::ios::binary | std::ios::ate) {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
throw std::runtime_error("could not to open file " + filename.string());
|
throw std::runtime_error("could not to open file " + filename.string());
|
||||||
}
|
}
|
||||||
@ -37,121 +71,92 @@ void io::rafile::read(char* buffer, std::streamsize size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool io::write_bytes(
|
bool io::write_bytes(
|
||||||
const fs::path& filename, const ubyte* data, size_t size
|
const io::path& filename, const ubyte* data, size_t size
|
||||||
) {
|
) {
|
||||||
std::ofstream output(filename, std::ios::binary);
|
auto device = io::get_device(filename.entryPoint());
|
||||||
if (!output.is_open()) return false;
|
if (device == nullptr) {
|
||||||
output.write((const char*)data, size);
|
return false;
|
||||||
output.close();
|
}
|
||||||
|
device->write(filename.pathPart(), data, size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint io::append_bytes(
|
bool io::read(const io::path& filename, char* data, size_t size) {
|
||||||
const fs::path& filename, const ubyte* data, size_t size
|
auto device = io::get_device(filename.entryPoint());
|
||||||
) {
|
if (device == nullptr) {
|
||||||
std::ofstream output(filename, std::ios::binary | std::ios::app);
|
return false;
|
||||||
if (!output.is_open()) return 0;
|
}
|
||||||
uint position = output.tellp();
|
device->read(filename.pathPart(), data, size);
|
||||||
output.write((const char*)data, size);
|
|
||||||
output.close();
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool io::read(const fs::path& filename, char* data, size_t size) {
|
|
||||||
std::ifstream output(filename, std::ios::binary);
|
|
||||||
if (!output.is_open()) return false;
|
|
||||||
output.read(data, size);
|
|
||||||
output.close();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Buffer<ubyte> io::read_bytes_buffer(const fs::path& path) {
|
util::Buffer<ubyte> io::read_bytes_buffer(const path& file) {
|
||||||
size_t size;
|
size_t size;
|
||||||
auto bytes = io::read_bytes(path, size);
|
auto bytes = io::read_bytes(file, size);
|
||||||
return util::Buffer<ubyte>(std::move(bytes), size);
|
return util::Buffer<ubyte>(std::move(bytes), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ubyte[]> io::read_bytes(
|
std::unique_ptr<ubyte[]> io::read_bytes(
|
||||||
const fs::path& filename, size_t& length
|
const io::path& filename, size_t& length
|
||||||
) {
|
) {
|
||||||
std::ifstream input(filename, std::ios::binary);
|
auto& device = io::require_device(filename.entryPoint());
|
||||||
if (!input.is_open()) {
|
length = device.size(filename.pathPart());
|
||||||
throw std::runtime_error(
|
|
||||||
"could not to load file '" + filename.string() + "'"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
input.seekg(0, std::ios_base::end);
|
|
||||||
length = input.tellg();
|
|
||||||
input.seekg(0, std::ios_base::beg);
|
|
||||||
|
|
||||||
auto data = std::make_unique<ubyte[]>(length);
|
auto data = std::make_unique<ubyte[]>(length);
|
||||||
input.read((char*)data.get(), length);
|
device.read(filename.pathPart(), data.get(), length);
|
||||||
input.close();
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ubyte> io::read_bytes(const fs::path& filename) {
|
std::vector<ubyte> io::read_bytes(const path& filename) {
|
||||||
std::ifstream input(filename, std::ios::binary);
|
auto& device = io::require_device(filename.entryPoint());
|
||||||
if (!input.is_open()) return {};
|
size_t length = device.size(filename.pathPart());
|
||||||
input.seekg(0, std::ios_base::end);
|
|
||||||
size_t length = input.tellg();
|
|
||||||
input.seekg(0, std::ios_base::beg);
|
|
||||||
|
|
||||||
std::vector<ubyte> data(length);
|
std::vector<ubyte> data(length);
|
||||||
data.resize(length);
|
device.read(filename.pathPart(), data.data(), length);
|
||||||
input.read((char*)data.data(), length);
|
|
||||||
input.close();
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string io::read_string(const fs::path& filename) {
|
std::string io::read_string(const path& filename) {
|
||||||
size_t size;
|
size_t size;
|
||||||
auto bytes = read_bytes(filename, size);
|
auto bytes = read_bytes(filename, size);
|
||||||
return std::string((const char*)bytes.get(), size);
|
return std::string((const char*)bytes.get(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool io::write_string(const fs::path& filename, std::string_view content) {
|
bool io::write_string(const io::path& file, std::string_view content) {
|
||||||
std::ofstream file(filename);
|
return io::write_bytes(file, (const ubyte*)content.data(), content.size());
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
file << content;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool io::write_json(
|
bool io::write_json(
|
||||||
const fs::path& filename, const dv::value& obj, bool nice
|
const io::path& file, const dv::value& obj, bool nice
|
||||||
) {
|
) {
|
||||||
return io::write_string(filename, json::stringify(obj, nice, " "));
|
return io::write_string(file, json::stringify(obj, nice, " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool io::write_binary_json(
|
bool io::write_binary_json(
|
||||||
const fs::path& filename, const dv::value& obj, bool compression
|
const io::path& file, const dv::value& obj, bool compression
|
||||||
) {
|
) {
|
||||||
auto bytes = json::to_binary(obj, compression);
|
auto bytes = json::to_binary(obj, compression);
|
||||||
return io::write_bytes(filename, bytes.data(), bytes.size());
|
return io::write_bytes(file, bytes.data(), bytes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
dv::value io::read_json(const fs::path& filename) {
|
dv::value io::read_json(const path& filename) {
|
||||||
std::string text = io::read_string(filename);
|
std::string text = io::read_string(filename);
|
||||||
return json::parse(filename.string(), text);
|
return json::parse(filename.string(), text);
|
||||||
}
|
}
|
||||||
|
|
||||||
dv::value io::read_binary_json(const fs::path& file) {
|
dv::value io::read_binary_json(const path& file) {
|
||||||
size_t size;
|
size_t size;
|
||||||
auto bytes = io::read_bytes(file, size);
|
auto bytes = io::read_bytes(file, size);
|
||||||
return json::from_binary(bytes.get(), size);
|
return json::from_binary(bytes.get(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
dv::value io::read_toml(const fs::path& file) {
|
dv::value io::read_toml(const path& file) {
|
||||||
return toml::parse(file.u8string(), io::read_string(file));
|
return toml::parse(file.string(), io::read_string(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> io::read_list(const fs::path& filename) {
|
std::vector<std::string> io::read_list(const io::path& filename) {
|
||||||
std::ifstream file(filename);
|
std::ifstream file(resolve(filename)); // FIXME
|
||||||
if (!file) {
|
if (!file) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"could not to open file " + filename.u8string()
|
"could not to open file " + filename.string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
@ -165,6 +170,71 @@ std::vector<std::string> io::read_list(const fs::path& filename) {
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool io::is_regular_file(const io::path& file) {
|
||||||
|
if (file.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto device = io::get_device(file.entryPoint());
|
||||||
|
if (device == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return device->isfile(file.pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool io::is_directory(const io::path& file) {
|
||||||
|
if (file.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto device = io::get_device(file.entryPoint());
|
||||||
|
if (device == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return device->isdir(file.pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool io::exists(const io::path& file) {
|
||||||
|
if (file.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto device = io::get_device(file.entryPoint());
|
||||||
|
if (device == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return device->exists(file.pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool io::create_directories(const io::path& file) {
|
||||||
|
auto& device = io::require_device(file.entryPoint());
|
||||||
|
if (device.isdir(file.pathPart())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
device.mkdirs(file.pathPart());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool io::remove(const io::path& file) {
|
||||||
|
auto& device = io::require_device(file.entryPoint());
|
||||||
|
return device.remove(file.pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t io::remove_all(const io::path& file) {
|
||||||
|
auto& device = io::require_device(file.entryPoint());
|
||||||
|
return device.removeAll(file.pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t io::file_size(const io::path& file) {
|
||||||
|
auto& device = io::require_device(file.entryPoint());
|
||||||
|
return device.size(file.pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::path io::resolve(const io::path& file) {
|
||||||
|
auto device = io::get_device(file.entryPoint());
|
||||||
|
if (device == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return device->resolve(file.pathPart());
|
||||||
|
}
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "coders/json.hpp"
|
#include "coders/json.hpp"
|
||||||
@ -177,22 +247,22 @@ static std::map<fs::path, DecodeFunc> data_decoders {
|
|||||||
{fs::u8path(".toml"), toml::parse},
|
{fs::u8path(".toml"), toml::parse},
|
||||||
};
|
};
|
||||||
|
|
||||||
bool io::is_data_file(const fs::path& file) {
|
bool io::is_data_file(const io::path& file) {
|
||||||
return is_data_interchange_format(file.extension());
|
return is_data_interchange_format(file.extension());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool io::is_data_interchange_format(const fs::path& ext) {
|
bool io::is_data_interchange_format(const std::string& ext) {
|
||||||
return data_decoders.find(ext) != data_decoders.end();
|
return data_decoders.find(ext) != data_decoders.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
dv::value io::read_object(const fs::path& file) {
|
dv::value io::read_object(const path& file) {
|
||||||
const auto& found = data_decoders.find(file.extension());
|
const auto& found = data_decoders.find(file.extension());
|
||||||
if (found == data_decoders.end()) {
|
if (found == data_decoders.end()) {
|
||||||
throw std::runtime_error("unknown file format");
|
throw std::runtime_error("unknown file format");
|
||||||
}
|
}
|
||||||
auto text = read_string(file);
|
auto text = read_string(file);
|
||||||
try {
|
try {
|
||||||
return found->second(file.u8string(), text);
|
return found->second(file.string(), text);
|
||||||
} catch (const parsing_error& err) {
|
} catch (const parsing_error& err) {
|
||||||
throw std::runtime_error(err.errorLog());
|
throw std::runtime_error(err.errorLog());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,16 +9,25 @@
|
|||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
#include "util/Buffer.hpp"
|
#include "util/Buffer.hpp"
|
||||||
|
#include "path.hpp"
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
namespace io {
|
namespace io {
|
||||||
|
class Device;
|
||||||
|
|
||||||
|
void set_device(const std::string& name, std::shared_ptr<Device> device);
|
||||||
|
std::shared_ptr<Device> get_device(const std::string& name);
|
||||||
|
Device& require_device(const std::string& name);
|
||||||
|
|
||||||
|
void create_subdevice(
|
||||||
|
const std::string& name, const std::string& parent, const path& root
|
||||||
|
);
|
||||||
|
|
||||||
/// @brief Read-only random access file
|
/// @brief Read-only random access file
|
||||||
class rafile {
|
class rafile {
|
||||||
std::ifstream file;
|
std::ifstream file;
|
||||||
size_t filelength;
|
size_t filelength;
|
||||||
public:
|
public:
|
||||||
rafile(const fs::path& filename);
|
rafile(const path& filename);
|
||||||
|
|
||||||
void seekg(std::streampos pos);
|
void seekg(std::streampos pos);
|
||||||
void read(char* buffer, std::streamsize size);
|
void read(char* buffer, std::streamsize size);
|
||||||
@ -29,52 +38,56 @@ namespace io {
|
|||||||
/// @param file target file
|
/// @param file target file
|
||||||
/// @param data data bytes array
|
/// @param data data bytes array
|
||||||
/// @param size size of data bytes array
|
/// @param size size of data bytes array
|
||||||
bool write_bytes(const fs::path& file, const ubyte* data, size_t size);
|
bool write_bytes(const io::path& file, const ubyte* data, size_t size);
|
||||||
|
|
||||||
/// @brief Append bytes array to the file without any extra data
|
|
||||||
/// @param file target file
|
|
||||||
/// @param data data bytes array
|
|
||||||
/// @param size size of data bytes array
|
|
||||||
uint append_bytes(const fs::path& file, const ubyte* data, size_t size);
|
|
||||||
|
|
||||||
/// @brief Write string to the file
|
/// @brief Write string to the file
|
||||||
bool write_string(const fs::path& filename, std::string_view content);
|
bool write_string(const io::path& file, std::string_view content);
|
||||||
|
|
||||||
/// @brief Write dynamic data to the JSON file
|
/// @brief Write dynamic data to the JSON file
|
||||||
/// @param nice if true, human readable format will be used, otherwise
|
/// @param nice if true, human readable format will be used, otherwise
|
||||||
/// minimal
|
/// minimal
|
||||||
bool write_json(
|
bool write_json(
|
||||||
const fs::path& filename, const dv::value& obj, bool nice = true
|
const io::path& file, const dv::value& obj, bool nice = true
|
||||||
);
|
);
|
||||||
|
|
||||||
/// @brief Write dynamic data to the binary JSON file
|
/// @brief Write dynamic data to the binary JSON file
|
||||||
/// (see src/coders/binary_json_spec.md)
|
/// (see src/coders/binary_json_spec.md)
|
||||||
/// @param compressed use gzip compression
|
/// @param compressed use gzip compression
|
||||||
bool write_binary_json(
|
bool write_binary_json(
|
||||||
const fs::path& filename,
|
const io::path& file,
|
||||||
const dv::value& obj,
|
const dv::value& obj,
|
||||||
bool compressed = false
|
bool compressed = false
|
||||||
);
|
);
|
||||||
|
|
||||||
bool read(const fs::path&, char* data, size_t size);
|
bool read(const io::path& file, char* data, size_t size);
|
||||||
util::Buffer<ubyte> read_bytes_buffer(const fs::path&);
|
util::Buffer<ubyte> read_bytes_buffer(const path& file);
|
||||||
std::unique_ptr<ubyte[]> read_bytes(const fs::path&, size_t& length);
|
std::unique_ptr<ubyte[]> read_bytes(const path& file, size_t& length);
|
||||||
std::vector<ubyte> read_bytes(const fs::path&);
|
std::vector<ubyte> read_bytes(const path& file);
|
||||||
std::string read_string(const fs::path& filename);
|
std::string read_string(const path& file);
|
||||||
|
|
||||||
/// @brief Read JSON or BJSON file
|
/// @brief Read JSON or BJSON file
|
||||||
/// @param file *.json or *.bjson file
|
/// @param file *.json or *.bjson file
|
||||||
dv::value read_json(const fs::path& file);
|
dv::value read_json(const path& file);
|
||||||
|
|
||||||
dv::value read_binary_json(const fs::path& file);
|
dv::value read_binary_json(const path& file);
|
||||||
|
|
||||||
/// @brief Read TOML file
|
/// @brief Read TOML file
|
||||||
/// @param file *.toml file
|
/// @param file *.toml file
|
||||||
dv::value read_toml(const fs::path& file);
|
dv::value read_toml(const path& file);
|
||||||
|
|
||||||
std::vector<std::string> read_list(const fs::path& file);
|
std::vector<std::string> read_list(const io::path& file);
|
||||||
|
|
||||||
bool is_data_file(const fs::path& file);
|
bool is_regular_file(const io::path& file);
|
||||||
bool is_data_interchange_format(const fs::path& ext);
|
bool is_directory(const io::path& file);
|
||||||
dv::value read_object(const fs::path& file);
|
bool exists(const io::path& file);
|
||||||
|
bool create_directories(const io::path& file);
|
||||||
|
bool remove(const io::path& file);
|
||||||
|
uint64_t remove_all(const io::path& file);
|
||||||
|
size_t file_size(const io::path& file);
|
||||||
|
|
||||||
|
std::filesystem::path resolve(const io::path& file);
|
||||||
|
|
||||||
|
bool is_data_file(const io::path& file);
|
||||||
|
bool is_data_interchange_format(const std::string& ext);
|
||||||
|
dv::value read_object(const path& file);
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/io/path.cpp
Normal file
11
src/io/path.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "path.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
using namespace io;
|
||||||
|
|
||||||
|
void path::checkValid() const {
|
||||||
|
if (colonPos == std::string::npos) {
|
||||||
|
throw std::runtime_error("path entry point is not specified: " + str);
|
||||||
|
}
|
||||||
|
}
|
||||||
138
src/io/path.hpp
Normal file
138
src/io/path.hpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace io {
|
||||||
|
/// @brief std::filesystem::path project-specific alternative having
|
||||||
|
/// `entry_point:path` scheme and solving std::filesystem::path problems:
|
||||||
|
/// - implicit std::string conversions depending on compiler
|
||||||
|
/// - unicode path construction must be done with std::filesystem::u8path
|
||||||
|
class path {
|
||||||
|
public:
|
||||||
|
path() = default;
|
||||||
|
|
||||||
|
path(std::string str) : str(std::move(str)) {
|
||||||
|
colonPos = this->str.find(':');
|
||||||
|
|
||||||
|
size_t len = this->str.length();
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
if (this->str[i] == '\\') {
|
||||||
|
this->str[i] = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path(const char* str) : path(std::string(str)) {}
|
||||||
|
|
||||||
|
bool operator==(const std::string& other) const {
|
||||||
|
return str == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const path& other) const {
|
||||||
|
return str < other.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const path& other) const {
|
||||||
|
return str == other.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const char* other) const {
|
||||||
|
return str == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
path operator/(const char* child) const {
|
||||||
|
if (str.empty() || str[str.length()-1] == ':') {
|
||||||
|
return str + std::string(child);
|
||||||
|
}
|
||||||
|
return str + "/" + std::string(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
path operator/(const std::string& child) const {
|
||||||
|
if (str.empty() || str[str.length()-1] == ':') {
|
||||||
|
return str + child;
|
||||||
|
}
|
||||||
|
return str + "/" + child;
|
||||||
|
}
|
||||||
|
|
||||||
|
path operator/(std::string_view child) const {
|
||||||
|
if (str.empty() || str[str.length()-1] == ':') {
|
||||||
|
return str + std::string(child);
|
||||||
|
}
|
||||||
|
return str + "/" + std::string(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
path operator/(const path& child) const {
|
||||||
|
if (str.empty() || str[str.length()-1] == ':') {
|
||||||
|
return str + child.pathPart();
|
||||||
|
}
|
||||||
|
return str + "/" + child.pathPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string pathPart() const {
|
||||||
|
if (colonPos == std::string::npos) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
return str.substr(colonPos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name() const {
|
||||||
|
size_t slashpos = str.rfind('/');
|
||||||
|
if (slashpos == std::string::npos) {
|
||||||
|
return colonPos == std::string::npos ? str
|
||||||
|
: str.substr(colonPos + 1);
|
||||||
|
}
|
||||||
|
return str.substr(slashpos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string stem() const {
|
||||||
|
return name().substr(0, name().rfind('.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Get extension
|
||||||
|
std::string extension() const {
|
||||||
|
size_t slashpos = str.rfind('/');
|
||||||
|
size_t dotpos = str.rfind('.');
|
||||||
|
if (dotpos == std::string::npos ||
|
||||||
|
(slashpos != std::string::npos && dotpos < slashpos)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return str.substr(dotpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Get entry point
|
||||||
|
std::string entryPoint() const {
|
||||||
|
checkValid();
|
||||||
|
return str.substr(0, colonPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Get parent path
|
||||||
|
path parent() const {
|
||||||
|
size_t slashpos = str.rfind('/');
|
||||||
|
if (slashpos == std::string::npos) {
|
||||||
|
return colonPos == std::string::npos
|
||||||
|
? path()
|
||||||
|
: path(str.substr(0, colonPos));
|
||||||
|
}
|
||||||
|
return colonPos == std::string::npos
|
||||||
|
? path(str.substr(0, slashpos))
|
||||||
|
: path(str.substr(0, colonPos) + str.substr(slashpos));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string string() const {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Check if path is not initialized with 'entry_point:path'
|
||||||
|
bool empty() const {
|
||||||
|
return str.empty();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/// @brief UTF-8 string contains entry_point:path or empty string
|
||||||
|
std::string str;
|
||||||
|
/// @brief Precalculated position of colon character
|
||||||
|
size_t colonPos = std::string::npos;
|
||||||
|
|
||||||
|
void checkValid() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -32,11 +32,11 @@ EngineController::EngineController(Engine& engine) : engine(engine) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EngineController::deleteWorld(const std::string& name) {
|
void EngineController::deleteWorld(const std::string& name) {
|
||||||
fs::path folder = engine.getPaths().getWorldFolderByName(name);
|
io::path folder = engine.getPaths().getWorldFolderByName(name);
|
||||||
|
|
||||||
auto deletion = [this, folder]() {
|
auto deletion = [this, folder]() {
|
||||||
logger.info() << "deleting " << folder;
|
logger.info() << "deleting " << folder.string();
|
||||||
fs::remove_all(folder);
|
io::remove_all(folder);
|
||||||
if (!engine.isHeadless()) {
|
if (!engine.isHeadless()) {
|
||||||
engine.getGUI()->getMenu()->back();
|
engine.getGUI()->getMenu()->back();
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ void EngineController::deleteWorld(const std::string& name) {
|
|||||||
guiutil::confirm(
|
guiutil::confirm(
|
||||||
engine,
|
engine,
|
||||||
langs::get(L"delete-confirm", L"world") + L" (" +
|
langs::get(L"delete-confirm", L"world") + L" (" +
|
||||||
util::str2wstr_utf8(folder.u8string()) + L")",
|
util::str2wstr_utf8(folder.string()) + L")",
|
||||||
deletion
|
deletion
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ static void show_convert_request(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool load_world_content(Engine& engine, const fs::path& folder) {
|
static bool load_world_content(Engine& engine, const io::path& folder) {
|
||||||
if (engine.isHeadless()) {
|
if (engine.isHeadless()) {
|
||||||
engine.loadWorldContent(folder);
|
engine.loadWorldContent(folder);
|
||||||
return true;
|
return true;
|
||||||
@ -192,10 +192,10 @@ void EngineController::onMissingContent(const std::shared_ptr<ContentReport>& re
|
|||||||
|
|
||||||
void EngineController::openWorld(const std::string& name, bool confirmConvert) {
|
void EngineController::openWorld(const std::string& name, bool confirmConvert) {
|
||||||
const auto& paths = engine.getPaths();
|
const auto& paths = engine.getPaths();
|
||||||
auto folder = paths.getWorldsFolder() / fs::u8path(name);
|
auto folder = paths.getWorldsFolder() / name;
|
||||||
auto worldFile = folder / fs::u8path("world.json");
|
auto worldFile = folder / "world.json";
|
||||||
if (!fs::exists(worldFile)) {
|
if (!io::exists(worldFile)) {
|
||||||
throw std::runtime_error(worldFile.u8string() + " does not exists");
|
throw std::runtime_error(worldFile.string() + " does not exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!load_world_content(engine, folder)) {
|
if (!load_world_content(engine, folder)) {
|
||||||
@ -257,7 +257,7 @@ void EngineController::createWorld(
|
|||||||
uint64_t seed = str2seed(seedstr);
|
uint64_t seed = str2seed(seedstr);
|
||||||
|
|
||||||
EnginePaths& paths = engine.getPaths();
|
EnginePaths& paths = engine.getPaths();
|
||||||
auto folder = paths.getWorldsFolder() / fs::u8path(name);
|
auto folder = paths.getWorldsFolder() / name;
|
||||||
|
|
||||||
if (engine.isHeadless()) {
|
if (engine.isHeadless()) {
|
||||||
engine.loadContent();
|
engine.loadContent();
|
||||||
@ -288,7 +288,7 @@ void EngineController::setLocalPlayer(int64_t player) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EngineController::reopenWorld(World* world) {
|
void EngineController::reopenWorld(World* world) {
|
||||||
std::string name = world->wfile->getFolder().filename().u8string();
|
std::string name = world->wfile->getFolder().name();
|
||||||
engine.onWorldClosed();
|
engine.onWorldClosed();
|
||||||
openWorld(name, true);
|
openWorld(name, true);
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ void EngineController::reconfigPacks(
|
|||||||
runnable removeFunc = [this, controller, packsToAdd, packsToRemove]() {
|
runnable removeFunc = [this, controller, packsToAdd, packsToRemove]() {
|
||||||
if (controller == nullptr) {
|
if (controller == nullptr) {
|
||||||
try {
|
try {
|
||||||
auto manager = engine.createPacksManager(fs::path(""));
|
auto manager = engine.createPacksManager("");
|
||||||
manager.scan();
|
manager.scan();
|
||||||
auto names = PacksManager::getNames(engine.getContentPacks());
|
auto names = PacksManager::getNames(engine.getContentPacks());
|
||||||
for (const auto& id : packsToAdd) {
|
for (const auto& id : packsToAdd) {
|
||||||
|
|||||||
@ -260,7 +260,7 @@ static int l_load_texture(lua::State* L) {
|
|||||||
|
|
||||||
static int l_open_folder(lua::State* L) {
|
static int l_open_folder(lua::State* L) {
|
||||||
auto path = engine->getPaths().resolve(lua::require_string(L, 1));
|
auto path = engine->getPaths().resolve(lua::require_string(L, 1));
|
||||||
platform::open_folder(path);
|
platform::open_folder(io::resolve(path));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,13 +13,13 @@
|
|||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
using namespace scripting;
|
using namespace scripting;
|
||||||
|
|
||||||
static fs::path resolve_path(const std::string& path) {
|
static io::path resolve_path(const std::string& path) {
|
||||||
return engine->getPaths().resolve(path);
|
return engine->getPaths().resolve(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fs::path resolve_path_soft(const std::string& path) {
|
static io::path resolve_path_soft(const std::string& path) {
|
||||||
if (path.find(':') == std::string::npos) {
|
if (path.find(':') == std::string::npos) {
|
||||||
return fs::u8path("");
|
return "";
|
||||||
}
|
}
|
||||||
return engine->getPaths().resolve(path, false);
|
return engine->getPaths().resolve(path, false);
|
||||||
}
|
}
|
||||||
@ -34,17 +34,17 @@ static int l_find(lua::State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int l_resolve(lua::State* L) {
|
static int l_resolve(lua::State* L) {
|
||||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
io::path path = resolve_path(lua::require_string(L, 1));
|
||||||
return lua::pushstring(L, path.u8string());
|
return lua::pushstring(L, path.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_read(lua::State* L) {
|
static int l_read(lua::State* L) {
|
||||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
io::path path = resolve_path(lua::require_string(L, 1));
|
||||||
if (fs::is_regular_file(path)) {
|
if (io::is_regular_file(path)) {
|
||||||
return lua::pushstring(L, io::read_string(path));
|
return lua::pushstring(L, io::read_string(path));
|
||||||
}
|
}
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"file does not exists " + util::quote(path.u8string())
|
"file does not exists " + util::quote(path.string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,9 +52,9 @@ static std::set<std::string> writeable_entry_points {
|
|||||||
"world", "export", "config"
|
"world", "export", "config"
|
||||||
};
|
};
|
||||||
|
|
||||||
static fs::path get_writeable_path(lua::State* L) {
|
static io::path get_writeable_path(lua::State* L) {
|
||||||
std::string rawpath = lua::require_string(L, 1);
|
std::string rawpath = lua::require_string(L, 1);
|
||||||
fs::path path = resolve_path(rawpath);
|
io::path path = resolve_path(rawpath);
|
||||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||||
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
||||||
throw std::runtime_error("access denied");
|
throw std::runtime_error("access denied");
|
||||||
@ -63,7 +63,7 @@ static fs::path get_writeable_path(lua::State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int l_write(lua::State* L) {
|
static int l_write(lua::State* L) {
|
||||||
fs::path path = get_writeable_path(L);
|
io::path path = get_writeable_path(L);
|
||||||
std::string text = lua::require_string(L, 2);
|
std::string text = lua::require_string(L, 2);
|
||||||
io::write_string(path, text);
|
io::write_string(path, text);
|
||||||
return 1;
|
return 1;
|
||||||
@ -71,62 +71,62 @@ static int l_write(lua::State* L) {
|
|||||||
|
|
||||||
static int l_remove(lua::State* L) {
|
static int l_remove(lua::State* L) {
|
||||||
std::string rawpath = lua::require_string(L, 1);
|
std::string rawpath = lua::require_string(L, 1);
|
||||||
fs::path path = resolve_path(rawpath);
|
io::path path = resolve_path(rawpath);
|
||||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||||
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
||||||
throw std::runtime_error("access denied");
|
throw std::runtime_error("access denied");
|
||||||
}
|
}
|
||||||
return lua::pushboolean(L, fs::remove(path));
|
return lua::pushboolean(L, io::remove(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_remove_tree(lua::State* L) {
|
static int l_remove_tree(lua::State* L) {
|
||||||
std::string rawpath = lua::require_string(L, 1);
|
std::string rawpath = lua::require_string(L, 1);
|
||||||
fs::path path = resolve_path(rawpath);
|
io::path path = resolve_path(rawpath);
|
||||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||||
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
||||||
throw std::runtime_error("access denied");
|
throw std::runtime_error("access denied");
|
||||||
}
|
}
|
||||||
return lua::pushinteger(L, fs::remove_all(path));
|
return lua::pushinteger(L, io::remove_all(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_exists(lua::State* L) {
|
static int l_exists(lua::State* L) {
|
||||||
fs::path path = resolve_path_soft(lua::require_string(L, 1));
|
io::path path = resolve_path_soft(lua::require_string(L, 1));
|
||||||
return lua::pushboolean(L, fs::exists(path));
|
return lua::pushboolean(L, io::exists(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_isfile(lua::State* L) {
|
static int l_isfile(lua::State* L) {
|
||||||
fs::path path = resolve_path_soft(lua::require_string(L, 1));
|
io::path path = resolve_path_soft(lua::require_string(L, 1));
|
||||||
return lua::pushboolean(L, fs::is_regular_file(path));
|
return lua::pushboolean(L, io::is_regular_file(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_isdir(lua::State* L) {
|
static int l_isdir(lua::State* L) {
|
||||||
fs::path path = resolve_path_soft(lua::require_string(L, 1));
|
io::path path = resolve_path_soft(lua::require_string(L, 1));
|
||||||
return lua::pushboolean(L, fs::is_directory(path));
|
return lua::pushboolean(L, io::is_directory(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_length(lua::State* L) {
|
static int l_length(lua::State* L) {
|
||||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
io::path path = resolve_path(lua::require_string(L, 1));
|
||||||
if (fs::exists(path)) {
|
if (io::exists(path)) {
|
||||||
return lua::pushinteger(L, fs::file_size(path));
|
return lua::pushinteger(L, io::file_size(path));
|
||||||
} else {
|
} else {
|
||||||
return lua::pushinteger(L, -1);
|
return lua::pushinteger(L, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_mkdir(lua::State* L) {
|
static int l_mkdir(lua::State* L) {
|
||||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
io::path path = resolve_path(lua::require_string(L, 1));
|
||||||
return lua::pushboolean(L, fs::create_directory(path));
|
return lua::pushboolean(L, io::create_directories(path)); // FIXME
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_mkdirs(lua::State* L) {
|
static int l_mkdirs(lua::State* L) {
|
||||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
io::path path = resolve_path(lua::require_string(L, 1));
|
||||||
return lua::pushboolean(L, fs::create_directories(path));
|
return lua::pushboolean(L, io::create_directories(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_read_bytes(lua::State* L) {
|
static int l_read_bytes(lua::State* L) {
|
||||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
io::path path = resolve_path(lua::require_string(L, 1));
|
||||||
if (fs::is_regular_file(path)) {
|
if (io::is_regular_file(path)) {
|
||||||
size_t length = static_cast<size_t>(fs::file_size(path));
|
size_t length = static_cast<size_t>(io::file_size(path));
|
||||||
|
|
||||||
auto bytes = io::read_bytes(path, length);
|
auto bytes = io::read_bytes(path, length);
|
||||||
|
|
||||||
@ -140,12 +140,12 @@ static int l_read_bytes(lua::State* L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"file does not exists " + util::quote(path.u8string())
|
"file does not exists " + util::quote(path.string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_write_bytes(lua::State* L) {
|
static int l_write_bytes(lua::State* L) {
|
||||||
fs::path path = get_writeable_path(L);
|
io::path path = get_writeable_path(L);
|
||||||
|
|
||||||
if (auto bytearray = lua::touserdata<lua::LuaBytearray>(L, 2)) {
|
if (auto bytearray = lua::touserdata<lua::LuaBytearray>(L, 2)) {
|
||||||
auto& bytes = bytearray->data();
|
auto& bytes = bytearray->data();
|
||||||
@ -176,15 +176,15 @@ static int l_list(lua::State* L) {
|
|||||||
if (dirname.find(':') == std::string::npos) {
|
if (dirname.find(':') == std::string::npos) {
|
||||||
return l_list_all_res(L, dirname);
|
return l_list_all_res(L, dirname);
|
||||||
}
|
}
|
||||||
fs::path path = resolve_path(dirname);
|
io::path path = resolve_path(dirname);
|
||||||
if (!fs::is_directory(path)) {
|
if (!io::is_directory(path)) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
util::quote(path.u8string()) + " is not a directory"
|
util::quote(path.string()) + " is not a directory"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
lua::createtable(L, 0, 0);
|
lua::createtable(L, 0, 0);
|
||||||
size_t index = 1;
|
size_t index = 1;
|
||||||
for (auto& entry : fs::directory_iterator(path)) {
|
for (auto& entry : fs::directory_iterator(io::resolve(path))) {
|
||||||
auto name = entry.path().filename().u8string();
|
auto name = entry.path().filename().u8string();
|
||||||
auto file = dirname + "/" + name;
|
auto file = dirname + "/" + name;
|
||||||
lua::pushstring(L, file);
|
lua::pushstring(L, file);
|
||||||
@ -240,7 +240,7 @@ static int l_read_combined_object(lua::State* L) {
|
|||||||
|
|
||||||
static int l_is_writeable(lua::State* L) {
|
static int l_is_writeable(lua::State* L) {
|
||||||
std::string rawpath = lua::require_string(L, 1);
|
std::string rawpath = lua::require_string(L, 1);
|
||||||
fs::path path = resolve_path(rawpath);
|
io::path path = resolve_path(rawpath);
|
||||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||||
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) {
|
||||||
return lua::pushboolean(L, false);
|
return lua::pushboolean(L, false);
|
||||||
|
|||||||
@ -38,8 +38,8 @@ static int l_load_fragment(lua::State* L) {
|
|||||||
const auto& paths = engine->getPaths();
|
const auto& paths = engine->getPaths();
|
||||||
auto filename = lua::require_string(L, 1);
|
auto filename = lua::require_string(L, 1);
|
||||||
auto path = paths.resolve(filename);
|
auto path = paths.resolve(filename);
|
||||||
if (!std::filesystem::exists(path)) {
|
if (!io::exists(path)) {
|
||||||
throw std::runtime_error("file "+path.u8string()+" does not exist");
|
throw std::runtime_error("file "+path.string()+" does not exist");
|
||||||
}
|
}
|
||||||
auto map = io::read_binary_json(path);
|
auto map = io::read_binary_json(path);
|
||||||
|
|
||||||
|
|||||||
@ -135,12 +135,12 @@ static int l_is_pressed(lua::State* L) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resetPackBindings(fs::path& packFolder) {
|
static void reset_pack_bindings(const io::path& packFolder) {
|
||||||
auto configFolder = packFolder/fs::path("config");
|
auto configFolder = packFolder / "config";
|
||||||
auto bindsFile = configFolder/fs::path("bindings.toml");
|
auto bindsFile = configFolder / "bindings.toml";
|
||||||
if (fs::is_regular_file(bindsFile)) {
|
if (io::is_regular_file(bindsFile)) {
|
||||||
Events::loadBindings(
|
Events::loadBindings(
|
||||||
bindsFile.u8string(),
|
bindsFile.string(),
|
||||||
io::read_string(bindsFile),
|
io::read_string(bindsFile),
|
||||||
BindType::REBIND
|
BindType::REBIND
|
||||||
);
|
);
|
||||||
@ -148,10 +148,9 @@ static void resetPackBindings(fs::path& packFolder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int l_reset_bindings(lua::State*) {
|
static int l_reset_bindings(lua::State*) {
|
||||||
auto resFolder = engine->getPaths().getResourcesFolder();
|
reset_pack_bindings("res:");
|
||||||
resetPackBindings(resFolder);
|
|
||||||
for (auto& pack : engine->getContentPacks()) {
|
for (auto& pack : engine->getContentPacks()) {
|
||||||
resetPackBindings(pack.folder);
|
reset_pack_bindings(pack.folder);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ static int l_pack_get_folder(lua::State* L) {
|
|||||||
|
|
||||||
for (auto& pack : packs) {
|
for (auto& pack : packs) {
|
||||||
if (pack.id == packName) {
|
if (pack.id == packName) {
|
||||||
return lua::pushstring(L, pack.folder.u8string() + "/");
|
return lua::pushstring(L, pack.folder.string() + "/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lua::pushstring(L, "");
|
return lua::pushstring(L, "");
|
||||||
@ -40,7 +40,7 @@ static int l_pack_get_installed(lua::State* L) {
|
|||||||
|
|
||||||
/// @brief pack.get_available() -> array<string>
|
/// @brief pack.get_available() -> array<string>
|
||||||
static int l_pack_get_available(lua::State* L) {
|
static int l_pack_get_available(lua::State* L) {
|
||||||
fs::path worldFolder("");
|
io::path worldFolder;
|
||||||
if (level) {
|
if (level) {
|
||||||
worldFolder = level->getWorld()->wfile->getFolder();
|
worldFolder = level->getWorld()->wfile->getFolder();
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ static int l_pack_get_info(
|
|||||||
auto assets = engine->getAssets();
|
auto assets = engine->getAssets();
|
||||||
std::string icon = pack.id + ".icon";
|
std::string icon = pack.id + ".icon";
|
||||||
if (!AssetsLoader::loadExternalTexture(
|
if (!AssetsLoader::loadExternalTexture(
|
||||||
assets, icon, {pack.folder / fs::path("icon.png")}
|
assets, icon, {pack.folder / "icon.png"}
|
||||||
)) {
|
)) {
|
||||||
icon = "gui/no_icon";
|
icon = "gui/no_icon";
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ static int pack_get_infos(lua::State* L) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ids.empty()) {
|
if (!ids.empty()) {
|
||||||
fs::path worldFolder("");
|
io::path worldFolder;
|
||||||
if (level) {
|
if (level) {
|
||||||
worldFolder = level->getWorld()->wfile->getFolder();
|
worldFolder = level->getWorld()->wfile->getFolder();
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ static int l_pack_get_info(lua::State* L) {
|
|||||||
return pack.id == packid;
|
return pack.id == packid;
|
||||||
});
|
});
|
||||||
if (found == packs.end()) {
|
if (found == packs.end()) {
|
||||||
fs::path worldFolder("");
|
io::path worldFolder;
|
||||||
if (level) {
|
if (level) {
|
||||||
worldFolder = level->getWorld()->wfile->getFolder();
|
worldFolder = level->getWorld()->wfile->getFolder();
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ static int l_pack_assemble(lua::State* L) {
|
|||||||
ids.push_back(lua::require_string(L, -1));
|
ids.push_back(lua::require_string(L, -1));
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
}
|
}
|
||||||
fs::path worldFolder("");
|
io::path worldFolder;
|
||||||
if (level) {
|
if (level) {
|
||||||
worldFolder = level->getWorld()->wfile->getFolder();
|
worldFolder = level->getWorld()->wfile->getFolder();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,7 @@ static int l_get_list(lua::State* L) {
|
|||||||
int versionMajor = versionMap["major"].asInteger();
|
int versionMajor = versionMap["major"].asInteger();
|
||||||
int versionMinor = versionMap["minor"].asInteger();
|
int versionMinor = versionMap["minor"].asInteger();
|
||||||
|
|
||||||
auto name = folder.filename().u8string();
|
auto name = folder.name();
|
||||||
lua::pushstring(L, name);
|
lua::pushstring(L, name);
|
||||||
lua::setfield(L, "name");
|
lua::setfield(L, "name");
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ static int l_get_seed(lua::State* L) {
|
|||||||
static int l_exists(lua::State* L) {
|
static int l_exists(lua::State* L) {
|
||||||
auto name = lua::require_string(L, 1);
|
auto name = lua::require_string(L, 1);
|
||||||
auto worldsDir = engine->getPaths().getWorldFolderByName(name);
|
auto worldsDir = engine->getPaths().getWorldFolderByName(name);
|
||||||
return lua::pushboolean(L, fs::is_directory(worldsDir));
|
return lua::pushboolean(L, io::is_directory(worldsDir));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_is_day(lua::State* L) {
|
static int l_is_day(lua::State* L) {
|
||||||
|
|||||||
@ -125,7 +125,7 @@ void lua::initialize(const EnginePaths& paths, const CoreParameters& params) {
|
|||||||
main_thread = create_state(
|
main_thread = create_state(
|
||||||
paths, params.headless ? StateType::SCRIPT : StateType::BASE
|
paths, params.headless ? StateType::SCRIPT : StateType::BASE
|
||||||
);
|
);
|
||||||
lua::pushstring(main_thread, params.scriptFile.stem().u8string());
|
lua::pushstring(main_thread, params.scriptFile.stem());
|
||||||
lua::setglobal(main_thread, "__VC_SCRIPT_NAME");
|
lua::setglobal(main_thread, "__VC_SCRIPT_NAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,8 +159,7 @@ State* lua::create_state(const EnginePaths& paths, StateType stateType) {
|
|||||||
}
|
}
|
||||||
init_state(L, stateType);
|
init_state(L, stateType);
|
||||||
|
|
||||||
auto resDir = paths.getResourcesFolder();
|
auto file = "res:scripts/stdmin.lua";
|
||||||
auto file = resDir / fs::u8path("scripts/stdmin.lua");
|
|
||||||
auto src = io::read_string(file);
|
auto src = io::read_string(file);
|
||||||
lua::pop(L, lua::execute(L, 0, src, "core:scripts/stdmin.lua"));
|
lua::pop(L, lua::execute(L, 0, src, "core:scripts/stdmin.lua"));
|
||||||
return L;
|
return L;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include "libs/api_lua.hpp"
|
#include "libs/api_lua.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
|
|||||||
@ -68,7 +68,7 @@ static int l_dump(lua::State* L) {
|
|||||||
raster[i*3 + 2] = val;
|
raster[i*3 + 2] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imageio::write(file.u8string(), &image);
|
imageio::write(file, &image);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,12 +41,11 @@ const ContentIndices* scripting::indices = nullptr;
|
|||||||
BlocksController* scripting::blocks = nullptr;
|
BlocksController* scripting::blocks = nullptr;
|
||||||
LevelController* scripting::controller = nullptr;
|
LevelController* scripting::controller = nullptr;
|
||||||
|
|
||||||
void scripting::load_script(const fs::path& name, bool throwable) {
|
void scripting::load_script(const io::path& name, bool throwable) {
|
||||||
const auto& paths = scripting::engine->getPaths();
|
io::path file = io::path("res:scripts") / name;
|
||||||
fs::path file = paths.getResourcesFolder() / fs::path("scripts") / name;
|
|
||||||
std::string src = io::read_string(file);
|
std::string src = io::read_string(file);
|
||||||
auto L = lua::get_main_state();
|
auto L = lua::get_main_state();
|
||||||
lua::loadbuffer(L, 0, src, "core:scripts/"+name.u8string());
|
lua::loadbuffer(L, 0, src, "core:scripts/"+name.string());
|
||||||
if (throwable) {
|
if (throwable) {
|
||||||
lua::call(L, 0, 0);
|
lua::call(L, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -57,11 +56,11 @@ void scripting::load_script(const fs::path& name, bool throwable) {
|
|||||||
int scripting::load_script(
|
int scripting::load_script(
|
||||||
int env,
|
int env,
|
||||||
const std::string& type,
|
const std::string& type,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
) {
|
) {
|
||||||
std::string src = io::read_string(file);
|
std::string src = io::read_string(file);
|
||||||
logger.info() << "script (" << type << ") " << file.u8string();
|
logger.info() << "script (" << type << ") " << file.string();
|
||||||
return lua::execute(lua::get_main_state(), env, src, fileName);
|
return lua::execute(lua::get_main_state(), env, src, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,8 +68,8 @@ void scripting::initialize(Engine* engine) {
|
|||||||
scripting::engine = engine;
|
scripting::engine = engine;
|
||||||
lua::initialize(engine->getPaths(), engine->getCoreParameters());
|
lua::initialize(engine->getPaths(), engine->getCoreParameters());
|
||||||
|
|
||||||
load_script(fs::path("stdlib.lua"), true);
|
load_script(io::path("stdlib.lua"), true);
|
||||||
load_script(fs::path("classes.lua"), true);
|
load_script(io::path("classes.lua"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LuaCoroutine : public Process {
|
class LuaCoroutine : public Process {
|
||||||
@ -113,12 +112,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Process> scripting::start_coroutine(
|
std::unique_ptr<Process> scripting::start_coroutine(
|
||||||
const std::filesystem::path& script
|
const io::path& script
|
||||||
) {
|
) {
|
||||||
auto L = lua::get_main_state();
|
auto L = lua::get_main_state();
|
||||||
if (lua::getglobal(L, "__vc_start_coroutine")) {
|
if (lua::getglobal(L, "__vc_start_coroutine")) {
|
||||||
auto source = io::read_string(script);
|
auto source = io::read_string(script);
|
||||||
lua::loadbuffer(L, 0, source, script.filename().u8string());
|
lua::loadbuffer(L, 0, source, script.name());
|
||||||
if (lua::call(L, 1)) {
|
if (lua::call(L, 1)) {
|
||||||
int id = lua::tointeger(L, -1);
|
int id = lua::tointeger(L, -1);
|
||||||
lua::pop(L, 2);
|
lua::pop(L, 2);
|
||||||
@ -253,8 +252,8 @@ void scripting::on_content_load(Content* content) {
|
|||||||
lua::setfield(L, "properties");
|
lua::setfield(L, "properties");
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
}
|
}
|
||||||
load_script(fs::path("post_content.lua"), true);
|
load_script("post_content.lua", true);
|
||||||
load_script(fs::path("stdcmd.lua"), true);
|
load_script("stdcmd.lua", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::on_world_load(LevelController* controller) {
|
void scripting::on_world_load(LevelController* controller) {
|
||||||
@ -829,7 +828,7 @@ int scripting::get_values_on_stack() {
|
|||||||
void scripting::load_content_script(
|
void scripting::load_content_script(
|
||||||
const scriptenv& senv,
|
const scriptenv& senv,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
BlockFuncsSet& funcsset
|
BlockFuncsSet& funcsset
|
||||||
) {
|
) {
|
||||||
@ -854,7 +853,7 @@ void scripting::load_content_script(
|
|||||||
void scripting::load_content_script(
|
void scripting::load_content_script(
|
||||||
const scriptenv& senv,
|
const scriptenv& senv,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
ItemFuncsSet& funcsset
|
ItemFuncsSet& funcsset
|
||||||
) {
|
) {
|
||||||
@ -869,11 +868,11 @@ void scripting::load_content_script(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scripting::load_entity_component(
|
void scripting::load_entity_component(
|
||||||
const std::string& name, const fs::path& file, const std::string& fileName
|
const std::string& name, const io::path& file, const std::string& fileName
|
||||||
) {
|
) {
|
||||||
auto L = lua::get_main_state();
|
auto L = lua::get_main_state();
|
||||||
std::string src = io::read_string(file);
|
std::string src = io::read_string(file);
|
||||||
logger.info() << "script (component) " << file.u8string();
|
logger.info() << "script (component) " << file.string();
|
||||||
lua::loadbuffer(L, 0, src, fileName);
|
lua::loadbuffer(L, 0, src, fileName);
|
||||||
lua::store_in(L, lua::CHUNKS_TABLE, name);
|
lua::store_in(L, lua::CHUNKS_TABLE, name);
|
||||||
}
|
}
|
||||||
@ -881,7 +880,7 @@ void scripting::load_entity_component(
|
|||||||
void scripting::load_world_script(
|
void scripting::load_world_script(
|
||||||
const scriptenv& senv,
|
const scriptenv& senv,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
WorldFuncsSet& funcsset
|
WorldFuncsSet& funcsset
|
||||||
) {
|
) {
|
||||||
@ -917,7 +916,7 @@ void scripting::load_world_script(
|
|||||||
void scripting::load_layout_script(
|
void scripting::load_layout_script(
|
||||||
const scriptenv& senv,
|
const scriptenv& senv,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
uidocscript& script
|
uidocscript& script
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "io/fwd.hpp"
|
||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
#include "delegates.hpp"
|
#include "delegates.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
@ -61,7 +61,7 @@ namespace scripting {
|
|||||||
void process_post_runnables();
|
void process_post_runnables();
|
||||||
|
|
||||||
std::unique_ptr<Process> start_coroutine(
|
std::unique_ptr<Process> start_coroutine(
|
||||||
const std::filesystem::path& script
|
const io::path& script
|
||||||
);
|
);
|
||||||
|
|
||||||
void on_world_load(LevelController* controller);
|
void on_world_load(LevelController* controller);
|
||||||
@ -150,7 +150,7 @@ namespace scripting {
|
|||||||
void load_content_script(
|
void load_content_script(
|
||||||
const scriptenv& env,
|
const scriptenv& env,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
BlockFuncsSet& funcsset
|
BlockFuncsSet& funcsset
|
||||||
);
|
);
|
||||||
@ -164,7 +164,7 @@ namespace scripting {
|
|||||||
void load_content_script(
|
void load_content_script(
|
||||||
const scriptenv& env,
|
const scriptenv& env,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
ItemFuncsSet& funcsset
|
ItemFuncsSet& funcsset
|
||||||
);
|
);
|
||||||
@ -175,13 +175,13 @@ namespace scripting {
|
|||||||
/// @param fileName script file path using the engine format
|
/// @param fileName script file path using the engine format
|
||||||
void load_entity_component(
|
void load_entity_component(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
);
|
);
|
||||||
|
|
||||||
std::unique_ptr<GeneratorScript> load_generator(
|
std::unique_ptr<GeneratorScript> load_generator(
|
||||||
const GeneratorDef& def,
|
const GeneratorDef& def,
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& dirPath
|
const std::string& dirPath
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ namespace scripting {
|
|||||||
void load_world_script(
|
void load_world_script(
|
||||||
const scriptenv& env,
|
const scriptenv& env,
|
||||||
const std::string& packid,
|
const std::string& packid,
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
WorldFuncsSet& funcsset
|
WorldFuncsSet& funcsset
|
||||||
);
|
);
|
||||||
@ -207,7 +207,7 @@ namespace scripting {
|
|||||||
void load_layout_script(
|
void load_layout_script(
|
||||||
const scriptenv& env,
|
const scriptenv& env,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
uidocscript& script
|
uidocscript& script
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
|
||||||
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
namespace scripting {
|
namespace scripting {
|
||||||
void load_script(const std::filesystem::path& name, bool throwable);
|
void load_script(const io::path& name, bool throwable);
|
||||||
|
|
||||||
[[nodiscard]] int load_script(
|
[[nodiscard]] int load_script(
|
||||||
int env,
|
int env,
|
||||||
const std::string& type,
|
const std::string& type,
|
||||||
const std::filesystem::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,11 +19,11 @@ Hud* scripting::hud = nullptr;
|
|||||||
WorldRenderer* scripting::renderer = nullptr;
|
WorldRenderer* scripting::renderer = nullptr;
|
||||||
|
|
||||||
static void load_script(const std::string& name) {
|
static void load_script(const std::string& name) {
|
||||||
auto file = engine->getPaths().getResourcesFolder() / "scripts" / name;
|
auto file = io::path("res:scripts") / name;
|
||||||
std::string src = io::read_string(file);
|
std::string src = io::read_string(file);
|
||||||
logger.info() << "loading script " << file.u8string();
|
logger.info() << "loading script " << file.string();
|
||||||
|
|
||||||
lua::execute(lua::get_main_state(), 0, src, file.u8string());
|
lua::execute(lua::get_main_state(), 0, src, file.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) {
|
void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) {
|
||||||
@ -80,12 +80,12 @@ void scripting::on_frontend_close() {
|
|||||||
void scripting::load_hud_script(
|
void scripting::load_hud_script(
|
||||||
const scriptenv& senv,
|
const scriptenv& senv,
|
||||||
const std::string& packid,
|
const std::string& packid,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
) {
|
) {
|
||||||
int env = *senv;
|
int env = *senv;
|
||||||
std::string src = io::read_string(file);
|
std::string src = io::read_string(file);
|
||||||
logger.info() << "loading script " << file.u8string();
|
logger.info() << "loading script " << file.string();
|
||||||
|
|
||||||
lua::execute(lua::get_main_state(), env, src, fileName);
|
lua::execute(lua::get_main_state(), env, src, fileName);
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
#include "io/fwd.hpp"
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
class Hud;
|
class Hud;
|
||||||
class WorldRenderer;
|
class WorldRenderer;
|
||||||
@ -33,7 +31,7 @@ namespace scripting {
|
|||||||
void load_hud_script(
|
void load_hud_script(
|
||||||
const scriptenv& env,
|
const scriptenv& env,
|
||||||
const std::string& packid,
|
const std::string& packid,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -26,10 +26,15 @@ class LuaGeneratorScript : public GeneratorScript {
|
|||||||
const GeneratorDef& def;
|
const GeneratorDef& def;
|
||||||
scriptenv env = nullptr;
|
scriptenv env = nullptr;
|
||||||
|
|
||||||
fs::path file;
|
io::path file;
|
||||||
std::string dirPath;
|
std::string dirPath;
|
||||||
public:
|
public:
|
||||||
LuaGeneratorScript(State* L, const GeneratorDef& def, const fs::path& file, const std::string& dirPath)
|
LuaGeneratorScript(
|
||||||
|
State* L,
|
||||||
|
const GeneratorDef& def,
|
||||||
|
const io::path& file,
|
||||||
|
const std::string& dirPath
|
||||||
|
)
|
||||||
: L(L), def(def), file(file), dirPath(dirPath) {
|
: L(L), def(def), file(file), dirPath(dirPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,10 +59,10 @@ public:
|
|||||||
|
|
||||||
pop(L);
|
pop(L);
|
||||||
|
|
||||||
if (fs::exists(file)) {
|
if (io::exists(file)) {
|
||||||
std::string src = io::read_string(file);
|
std::string src = io::read_string(file);
|
||||||
logger.info() << "script (generator) " << file.u8string();
|
logger.info() << "script (generator) " << file.string();
|
||||||
pop(L, execute(L, *env, src, file.u8string()));
|
pop(L, execute(L, *env, src, file.string()));
|
||||||
} else {
|
} else {
|
||||||
// Use default (empty) script
|
// Use default (empty) script
|
||||||
pop(L, execute(L, *env, "", "<empty>"));
|
pop(L, execute(L, *env, "", "<empty>"));
|
||||||
@ -252,7 +257,7 @@ public:
|
|||||||
|
|
||||||
std::unique_ptr<GeneratorScript> scripting::load_generator(
|
std::unique_ptr<GeneratorScript> scripting::load_generator(
|
||||||
const GeneratorDef& def,
|
const GeneratorDef& def,
|
||||||
const fs::path& file,
|
const io::path& file,
|
||||||
const std::string& dirPath
|
const std::string& dirPath
|
||||||
) {
|
) {
|
||||||
auto L = create_state(engine->getPaths(), StateType::GENERATOR);
|
auto L = create_state(engine->getPaths(), StateType::GENERATOR);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "command_line.hpp"
|
#include "command_line.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "io/engine_paths.hpp"
|
#include "io/engine_paths.hpp"
|
||||||
@ -14,10 +13,10 @@ static bool perform_keyword(
|
|||||||
) {
|
) {
|
||||||
if (keyword == "--res") {
|
if (keyword == "--res") {
|
||||||
auto token = reader.next();
|
auto token = reader.next();
|
||||||
params.resFolder = fs::u8path(token);
|
params.resFolder = token;
|
||||||
} else if (keyword == "--dir") {
|
} else if (keyword == "--dir") {
|
||||||
auto token = reader.next();
|
auto token = reader.next();
|
||||||
params.userFolder = fs::u8path(token);
|
params.userFolder = token;
|
||||||
} else if (keyword == "--help" || keyword == "-h") {
|
} else if (keyword == "--help" || keyword == "-h") {
|
||||||
std::cout << "VoxelCore v" << ENGINE_VERSION_STRING << "\n\n";
|
std::cout << "VoxelCore v" << ENGINE_VERSION_STRING << "\n\n";
|
||||||
std::cout << "command-line arguments:\n";
|
std::cout << "command-line arguments:\n";
|
||||||
@ -38,11 +37,11 @@ static bool perform_keyword(
|
|||||||
} else if (keyword == "--test") {
|
} else if (keyword == "--test") {
|
||||||
auto token = reader.next();
|
auto token = reader.next();
|
||||||
params.testMode = true;
|
params.testMode = true;
|
||||||
params.scriptFile = fs::u8path(token);
|
params.scriptFile = token;
|
||||||
} else if (keyword == "--script") {
|
} else if (keyword == "--script") {
|
||||||
auto token = reader.next();
|
auto token = reader.next();
|
||||||
params.testMode = false;
|
params.testMode = false;
|
||||||
params.scriptFile = fs::u8path(token);
|
params.scriptFile = token;
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("unknown argument " + keyword);
|
throw std::runtime_error("unknown argument " + keyword);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,7 @@ void World::write(Level* level) {
|
|||||||
std::unique_ptr<Level> World::create(
|
std::unique_ptr<Level> World::create(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& generator,
|
const std::string& generator,
|
||||||
const fs::path& directory,
|
const io::path& directory,
|
||||||
uint64_t seed,
|
uint64_t seed,
|
||||||
EngineSettings& settings,
|
EngineSettings& settings,
|
||||||
const Content& content,
|
const Content& content,
|
||||||
@ -98,7 +98,7 @@ std::unique_ptr<Level> World::create(
|
|||||||
logger.info() << "created nameless world";
|
logger.info() << "created nameless world";
|
||||||
} else {
|
} else {
|
||||||
logger.info() << "created world '" << name << "' ("
|
logger.info() << "created world '" << name << "' ("
|
||||||
<< directory.u8string() << ")";
|
<< directory.string() << ")";
|
||||||
}
|
}
|
||||||
logger.info() << "world seed: " << seed << " generator: " << generator;
|
logger.info() << "world seed: " << seed << " generator: " << generator;
|
||||||
return std::make_unique<Level>(std::move(world), content, settings);
|
return std::make_unique<Level>(std::move(world), content, settings);
|
||||||
@ -116,7 +116,7 @@ std::unique_ptr<Level> World::load(
|
|||||||
throw world_load_error("could not to find world.json");
|
throw world_load_error("could not to find world.json");
|
||||||
}
|
}
|
||||||
logger.info() << "loading world " << info->name << " ("
|
logger.info() << "loading world " << info->name << " ("
|
||||||
<< worldFilesPtr->getFolder().u8string() << ")";
|
<< worldFilesPtr->getFolder().string() << ")";
|
||||||
logger.info() << "world version: " << info->major << "." << info->minor
|
logger.info() << "world version: " << info->major << "." << info->minor
|
||||||
<< " seed: " << info->seed
|
<< " seed: " << info->seed
|
||||||
<< " generator: " << info->generator;
|
<< " generator: " << info->generator;
|
||||||
@ -129,8 +129,8 @@ std::unique_ptr<Level> World::load(
|
|||||||
|
|
||||||
auto level = std::make_unique<Level>(std::move(world), content, settings);
|
auto level = std::make_unique<Level>(std::move(world), content, settings);
|
||||||
|
|
||||||
fs::path file = wfile->getPlayerFile();
|
io::path file = wfile->getPlayerFile();
|
||||||
if (!fs::is_regular_file(file)) {
|
if (!io::is_regular_file(file)) {
|
||||||
logger.warning() << "player.json does not exists";
|
logger.warning() << "player.json does not exists";
|
||||||
level->players->create();
|
level->players->create();
|
||||||
} else {
|
} else {
|
||||||
@ -149,8 +149,8 @@ std::unique_ptr<Level> World::load(
|
|||||||
std::shared_ptr<ContentReport> World::checkIndices(
|
std::shared_ptr<ContentReport> World::checkIndices(
|
||||||
const std::shared_ptr<WorldFiles>& worldFiles, const Content* content
|
const std::shared_ptr<WorldFiles>& worldFiles, const Content* content
|
||||||
) {
|
) {
|
||||||
fs::path indicesFile = worldFiles->getIndicesFile();
|
io::path indicesFile = worldFiles->getIndicesFile();
|
||||||
if (fs::is_regular_file(indicesFile)) {
|
if (io::is_regular_file(indicesFile)) {
|
||||||
return ContentReport::create(worldFiles, indicesFile, content);
|
return ContentReport::create(worldFiles, indicesFile, content);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "io/fwd.hpp"
|
||||||
#include "content/ContentPack.hpp"
|
#include "content/ContentPack.hpp"
|
||||||
#include "interfaces/Serializable.hpp"
|
#include "interfaces/Serializable.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
@ -16,8 +16,6 @@ class Level;
|
|||||||
class ContentReport;
|
class ContentReport;
|
||||||
struct EngineSettings;
|
struct EngineSettings;
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
class world_load_error : public std::runtime_error {
|
class world_load_error : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
world_load_error(const std::string& message);
|
world_load_error(const std::string& message);
|
||||||
@ -100,7 +98,7 @@ public:
|
|||||||
static std::unique_ptr<Level> create(
|
static std::unique_ptr<Level> create(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& generator,
|
const std::string& generator,
|
||||||
const fs::path& directory,
|
const io::path& directory,
|
||||||
uint64_t seed,
|
uint64_t seed,
|
||||||
EngineSettings& settings,
|
EngineSettings& settings,
|
||||||
const Content& content,
|
const Content& content,
|
||||||
|
|||||||
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
#define REGION_FORMAT_MAGIC ".VOXREG"
|
#define REGION_FORMAT_MAGIC ".VOXREG"
|
||||||
|
|
||||||
static fs::path get_region_filename(int x, int z) {
|
static io::path get_region_filename(int x, int z) {
|
||||||
return fs::path(std::to_string(x) + "_" + std::to_string(z) + ".bin");
|
return std::to_string(x) + "_" + std::to_string(z) + ".bin";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Read missing chunks data (null pointers) from region file
|
/// @brief Read missing chunks data (null pointers) from region file
|
||||||
@ -25,7 +25,7 @@ static void fetch_chunks(WorldRegion* region, int x, int z, regfile* file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regfile::regfile(fs::path filename) : file(std::move(filename)) {
|
regfile::regfile(io::path filename) : file(std::move(filename)) {
|
||||||
if (file.length() < REGION_HEADER_SIZE)
|
if (file.length() < REGION_HEADER_SIZE)
|
||||||
throw std::runtime_error("incomplete region file header");
|
throw std::runtime_error("incomplete region file header");
|
||||||
char header[REGION_HEADER_SIZE];
|
char header[REGION_HEADER_SIZE];
|
||||||
@ -98,8 +98,8 @@ regfile_ptr RegionsLayer::getRegFile(glm::ivec2 coord, bool create) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
regfile_ptr RegionsLayer::createRegFile(glm::ivec2 coord) {
|
regfile_ptr RegionsLayer::createRegFile(glm::ivec2 coord) {
|
||||||
auto file = folder / get_region_filename(coord[0], coord[1]);
|
auto file = folder / get_region_filename(coord[0], coord[1]);
|
||||||
if (!fs::exists(file)) {
|
if (!io::exists(file)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (openRegFiles.size() == MAX_OPEN_REGION_FILES) {
|
if (openRegFiles.size() == MAX_OPEN_REGION_FILES) {
|
||||||
@ -138,7 +138,7 @@ WorldRegion* RegionsLayer::getRegion(int x, int z) {
|
|||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path RegionsLayer::getRegionFilePath(int x, int z) const {
|
io::path RegionsLayer::getRegionFilePath(int x, int z) const {
|
||||||
return folder / get_region_filename(x, z);
|
return folder / get_region_filename(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ ubyte* RegionsLayer::getData(int x, int z, uint32_t& size, uint32_t& srcSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RegionsLayer::writeRegion(int x, int z, WorldRegion* entry) {
|
void RegionsLayer::writeRegion(int x, int z, WorldRegion* entry) {
|
||||||
fs::path filename = folder / get_region_filename(x, z);
|
io::path filename = folder / get_region_filename(x, z);
|
||||||
|
|
||||||
glm::ivec2 regcoord(x, z);
|
glm::ivec2 regcoord(x, z);
|
||||||
if (auto regfile = getRegFile(regcoord, false)) {
|
if (auto regfile = getRegFile(regcoord, false)) {
|
||||||
@ -193,7 +193,7 @@ void RegionsLayer::writeRegion(int x, int z, WorldRegion* entry) {
|
|||||||
char header[REGION_HEADER_SIZE] = REGION_FORMAT_MAGIC;
|
char header[REGION_HEADER_SIZE] = REGION_FORMAT_MAGIC;
|
||||||
header[8] = REGION_FORMAT_VERSION;
|
header[8] = REGION_FORMAT_VERSION;
|
||||||
header[9] = static_cast<ubyte>(compression); // FIXME
|
header[9] = static_cast<ubyte>(compression); // FIXME
|
||||||
std::ofstream file(filename, std::ios::out | std::ios::binary);
|
std::ofstream file(io::resolve(filename), std::ios::out | std::ios::binary);
|
||||||
file.write(header, REGION_HEADER_SIZE);
|
file.write(header, REGION_HEADER_SIZE);
|
||||||
|
|
||||||
size_t offset = REGION_HEADER_SIZE;
|
size_t offset = REGION_HEADER_SIZE;
|
||||||
|
|||||||
@ -39,17 +39,17 @@ void WorldConverter::addRegionsTasks(
|
|||||||
) {
|
) {
|
||||||
const auto& regions = wfile->getRegions();
|
const auto& regions = wfile->getRegions();
|
||||||
auto regionsFolder = regions.getRegionsFolder(layerid);
|
auto regionsFolder = regions.getRegionsFolder(layerid);
|
||||||
if (!fs::is_directory(regionsFolder)) {
|
if (!io::is_directory(regionsFolder)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto& file : fs::directory_iterator(regionsFolder)) {
|
for (const auto& file : fs::directory_iterator(io::resolve(regionsFolder))) {
|
||||||
int x, z;
|
int x, z;
|
||||||
std::string name = file.path().stem().string();
|
std::string name = file.path().stem().string();
|
||||||
if (!WorldRegions::parseRegionFilename(name, x, z)) {
|
if (!WorldRegions::parseRegionFilename(name, x, z)) {
|
||||||
logger.error() << "could not parse region name " << name;
|
logger.error() << "could not parse region name " << name;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tasks.push(ConvertTask {taskType, file.path(), x, z, layerid});
|
tasks.push(ConvertTask {taskType, file.path().u8string(), x, z, layerid});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ std::shared_ptr<Task> WorldConverter::startTask(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::upgradeRegion(
|
void WorldConverter::upgradeRegion(
|
||||||
const fs::path& file, int x, int z, RegionLayerIndex layer
|
const io::path& file, int x, int z, RegionLayerIndex layer
|
||||||
) const {
|
) const {
|
||||||
auto path = wfile->getRegions().getRegionFilePath(layer, x, z);
|
auto path = wfile->getRegions().getRegionFilePath(layer, x, z);
|
||||||
auto bytes = io::read_bytes_buffer(path);
|
auto bytes = io::read_bytes_buffer(path);
|
||||||
@ -190,7 +190,7 @@ void WorldConverter::upgradeRegion(
|
|||||||
io::write_bytes(path, buffer.data(), buffer.size());
|
io::write_bytes(path, buffer.data(), buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::convertVoxels(const fs::path& file, int x, int z) const {
|
void WorldConverter::convertVoxels(const io::path& file, int x, int z) const {
|
||||||
logger.info() << "converting voxels region " << x << "_" << z;
|
logger.info() << "converting voxels region " << x << "_" << z;
|
||||||
wfile->getRegions().processRegion(x, z, REGION_LAYER_VOXELS,
|
wfile->getRegions().processRegion(x, z, REGION_LAYER_VOXELS,
|
||||||
[=](std::unique_ptr<ubyte[]> data, uint32_t*) {
|
[=](std::unique_ptr<ubyte[]> data, uint32_t*) {
|
||||||
@ -199,15 +199,15 @@ void WorldConverter::convertVoxels(const fs::path& file, int x, int z) const {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::convertInventories(const fs::path& file, int x, int z) const {
|
void WorldConverter::convertInventories(const io::path& file, int x, int z) const {
|
||||||
logger.info() << "converting inventories region " << x << "_" << z;
|
logger.info() << "converting inventories region " << x << "_" << z;
|
||||||
wfile->getRegions().processInventories(x, z, [=](Inventory* inventory) {
|
wfile->getRegions().processInventories(x, z, [=](Inventory* inventory) {
|
||||||
inventory->convert(report.get());
|
inventory->convert(report.get());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::convertPlayer(const fs::path& file) const {
|
void WorldConverter::convertPlayer(const io::path& file) const {
|
||||||
logger.info() << "converting player " << file.u8string();
|
logger.info() << "converting player " << file.string();
|
||||||
auto map = io::read_json(file);
|
auto map = io::read_json(file);
|
||||||
Player::convert(map, report.get());
|
Player::convert(map, report.get());
|
||||||
io::write_json(file, map);
|
io::write_json(file, map);
|
||||||
@ -242,7 +242,7 @@ void WorldConverter::convertBlocksData(int x, int z, const ContentReport& report
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::convert(const ConvertTask& task) const {
|
void WorldConverter::convert(const ConvertTask& task) const {
|
||||||
if (!fs::is_regular_file(task.file)) return;
|
if (!io::is_regular_file(task.file)) return;
|
||||||
|
|
||||||
switch (task.type) {
|
switch (task.type) {
|
||||||
case ConvertTaskType::UPGRADE_REGION:
|
case ConvertTaskType::UPGRADE_REGION:
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "delegates.hpp"
|
#include "delegates.hpp"
|
||||||
#include "interfaces/Task.hpp"
|
#include "interfaces/Task.hpp"
|
||||||
|
#include "io/io.hpp"
|
||||||
#include "world/files/world_regions_fwd.hpp"
|
#include "world/files/world_regions_fwd.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
class Content;
|
class Content;
|
||||||
class ContentReport;
|
class ContentReport;
|
||||||
class WorldFiles;
|
class WorldFiles;
|
||||||
@ -30,7 +28,7 @@ enum class ConvertTaskType {
|
|||||||
|
|
||||||
struct ConvertTask {
|
struct ConvertTask {
|
||||||
ConvertTaskType type;
|
ConvertTaskType type;
|
||||||
fs::path file;
|
io::path file;
|
||||||
|
|
||||||
/// @brief region coords
|
/// @brief region coords
|
||||||
int x, z;
|
int x, z;
|
||||||
@ -53,10 +51,10 @@ class WorldConverter : public Task {
|
|||||||
ConvertMode mode;
|
ConvertMode mode;
|
||||||
|
|
||||||
void upgradeRegion(
|
void upgradeRegion(
|
||||||
const fs::path& file, int x, int z, RegionLayerIndex layer) const;
|
const io::path& file, int x, int z, RegionLayerIndex layer) const;
|
||||||
void convertPlayer(const fs::path& file) const;
|
void convertPlayer(const io::path& file) const;
|
||||||
void convertVoxels(const fs::path& file, int x, int z) const;
|
void convertVoxels(const io::path& file, int x, int z) const;
|
||||||
void convertInventories(const fs::path& file, int x, int z) const;
|
void convertInventories(const io::path& file, int x, int z) const;
|
||||||
void convertBlocksData(int x, int z, const ContentReport& report) const;
|
void convertBlocksData(int x, int z, const ContentReport& report) const;
|
||||||
|
|
||||||
void addRegionsTasks(
|
void addRegionsTasks(
|
||||||
|
|||||||
@ -36,11 +36,11 @@
|
|||||||
|
|
||||||
static debug::Logger logger("world-files");
|
static debug::Logger logger("world-files");
|
||||||
|
|
||||||
WorldFiles::WorldFiles(const fs::path& directory)
|
WorldFiles::WorldFiles(const io::path& directory)
|
||||||
: directory(directory), regions(directory) {
|
: directory(directory), regions(directory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldFiles::WorldFiles(const fs::path& directory, const DebugSettings& settings)
|
WorldFiles::WorldFiles(const io::path& directory, const DebugSettings& settings)
|
||||||
: WorldFiles(directory) {
|
: WorldFiles(directory) {
|
||||||
generatorTestMode = settings.generatorTestMode.get();
|
generatorTestMode = settings.generatorTestMode.get();
|
||||||
doWriteLights = settings.doWriteLights.get();
|
doWriteLights = settings.doWriteLights.get();
|
||||||
@ -51,28 +51,28 @@ WorldFiles::WorldFiles(const fs::path& directory, const DebugSettings& settings)
|
|||||||
WorldFiles::~WorldFiles() = default;
|
WorldFiles::~WorldFiles() = default;
|
||||||
|
|
||||||
void WorldFiles::createDirectories() {
|
void WorldFiles::createDirectories() {
|
||||||
fs::create_directories(directory / fs::path("data"));
|
io::create_directories(directory / "data");
|
||||||
fs::create_directories(directory / fs::path("content"));
|
io::create_directories(directory / "content");
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getPlayerFile() const {
|
io::path WorldFiles::getPlayerFile() const {
|
||||||
return directory / fs::path("player.json");
|
return directory / "player.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getResourcesFile() const {
|
io::path WorldFiles::getResourcesFile() const {
|
||||||
return directory / fs::path("resources.json");
|
return directory / "resources.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getWorldFile() const {
|
io::path WorldFiles::getWorldFile() const {
|
||||||
return directory / fs::path(WORLD_FILE);
|
return directory / WORLD_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getIndicesFile() const {
|
io::path WorldFiles::getIndicesFile() const {
|
||||||
return directory / fs::path("indices.json");
|
return directory / "indices.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getPacksFile() const {
|
io::path WorldFiles::getPacksFile() const {
|
||||||
return directory / fs::path("packs.list");
|
return directory / "packs.list";
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::write(
|
void WorldFiles::write(
|
||||||
@ -80,7 +80,7 @@ void WorldFiles::write(
|
|||||||
) {
|
) {
|
||||||
if (world) {
|
if (world) {
|
||||||
writeWorldInfo(world->getInfo());
|
writeWorldInfo(world->getInfo());
|
||||||
if (!fs::exists(getPacksFile())) {
|
if (!io::exists(getPacksFile())) {
|
||||||
writePacks(world->getPacks());
|
writePacks(world->getPacks());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,8 +147,8 @@ void WorldFiles::writeWorldInfo(const WorldInfo& info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<WorldInfo> WorldFiles::readWorldInfo() {
|
std::optional<WorldInfo> WorldFiles::readWorldInfo() {
|
||||||
fs::path file = getWorldFile();
|
io::path file = getWorldFile();
|
||||||
if (!fs::is_regular_file(file)) {
|
if (!io::is_regular_file(file)) {
|
||||||
logger.warning() << "world.json does not exists";
|
logger.warning() << "world.json does not exists";
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
@ -175,8 +175,8 @@ static void read_resources_data(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WorldFiles::readResourcesData(const Content& content) {
|
bool WorldFiles::readResourcesData(const Content& content) {
|
||||||
fs::path file = getResourcesFile();
|
io::path file = getResourcesFile();
|
||||||
if (!fs::is_regular_file(file)) {
|
if (!io::is_regular_file(file)) {
|
||||||
logger.warning() << "resources.json does not exists";
|
logger.warning() << "resources.json does not exists";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -192,9 +192,9 @@ bool WorldFiles::readResourcesData(const Content& content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::patchIndicesFile(const dv::value& map) {
|
void WorldFiles::patchIndicesFile(const dv::value& map) {
|
||||||
fs::path file = getIndicesFile();
|
io::path file = getIndicesFile();
|
||||||
if (!fs::is_regular_file(file)) {
|
if (!io::is_regular_file(file)) {
|
||||||
logger.error() << file.filename().u8string() << " does not exists";
|
logger.error() << file.name() << " does not exists";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
@ -230,6 +230,6 @@ void WorldFiles::removeIndices(const std::vector<std::string>& packs) {
|
|||||||
io::write_json(getIndicesFile(), root);
|
io::write_json(getIndicesFile(), root);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getFolder() const {
|
io::path WorldFiles::getFolder() const {
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -24,28 +23,26 @@ class World;
|
|||||||
struct WorldInfo;
|
struct WorldInfo;
|
||||||
struct DebugSettings;
|
struct DebugSettings;
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
class WorldFiles {
|
class WorldFiles {
|
||||||
fs::path directory;
|
io::path directory;
|
||||||
WorldRegions regions;
|
WorldRegions regions;
|
||||||
|
|
||||||
bool generatorTestMode = false;
|
bool generatorTestMode = false;
|
||||||
bool doWriteLights = true;
|
bool doWriteLights = true;
|
||||||
|
|
||||||
fs::path getWorldFile() const;
|
io::path getWorldFile() const;
|
||||||
fs::path getPacksFile() const;
|
io::path getPacksFile() const;
|
||||||
|
|
||||||
void writeWorldInfo(const WorldInfo& info);
|
void writeWorldInfo(const WorldInfo& info);
|
||||||
void writeIndices(const ContentIndices* indices);
|
void writeIndices(const ContentIndices* indices);
|
||||||
public:
|
public:
|
||||||
WorldFiles(const fs::path& directory);
|
WorldFiles(const io::path& directory);
|
||||||
WorldFiles(const fs::path& directory, const DebugSettings& settings);
|
WorldFiles(const io::path& directory, const DebugSettings& settings);
|
||||||
~WorldFiles();
|
~WorldFiles();
|
||||||
|
|
||||||
fs::path getPlayerFile() const;
|
io::path getPlayerFile() const;
|
||||||
fs::path getIndicesFile() const;
|
io::path getIndicesFile() const;
|
||||||
fs::path getResourcesFile() const;
|
io::path getResourcesFile() const;
|
||||||
void createDirectories();
|
void createDirectories();
|
||||||
|
|
||||||
std::optional<WorldInfo> readWorldInfo();
|
std::optional<WorldInfo> readWorldInfo();
|
||||||
@ -70,7 +67,7 @@ public:
|
|||||||
void removeIndices(const std::vector<std::string>& packs);
|
void removeIndices(const std::vector<std::string>& packs);
|
||||||
|
|
||||||
/// @return world folder
|
/// @return world folder
|
||||||
fs::path getFolder() const;
|
io::path getFolder() const;
|
||||||
|
|
||||||
WorldRegions& getRegions() {
|
WorldRegions& getRegions() {
|
||||||
return regions;
|
return regions;
|
||||||
|
|||||||
@ -57,24 +57,24 @@ glm::u32vec2 WorldRegion::getChunkDataSize(uint x, uint z) {
|
|||||||
return sizes[z * REGION_SIZE + x];
|
return sizes[z * REGION_SIZE + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldRegions::WorldRegions(const fs::path& directory) : directory(directory) {
|
WorldRegions::WorldRegions(const io::path& directory) : directory(directory) {
|
||||||
for (size_t i = 0; i < REGION_LAYERS_COUNT; i++) {
|
for (size_t i = 0; i < REGION_LAYERS_COUNT; i++) {
|
||||||
layers[i].layer = static_cast<RegionLayerIndex>(i);
|
layers[i].layer = static_cast<RegionLayerIndex>(i);
|
||||||
}
|
}
|
||||||
auto& voxels = layers[REGION_LAYER_VOXELS];
|
auto& voxels = layers[REGION_LAYER_VOXELS];
|
||||||
voxels.folder = directory / fs::path("regions");
|
voxels.folder = directory / "regions";
|
||||||
voxels.compression = compression::Method::EXTRLE16;
|
voxels.compression = compression::Method::EXTRLE16;
|
||||||
|
|
||||||
auto& lights = layers[REGION_LAYER_LIGHTS];
|
auto& lights = layers[REGION_LAYER_LIGHTS];
|
||||||
lights.folder = directory / fs::path("lights");
|
lights.folder = directory / "lights";
|
||||||
lights.compression = compression::Method::EXTRLE8;
|
lights.compression = compression::Method::EXTRLE8;
|
||||||
|
|
||||||
layers[REGION_LAYER_INVENTORIES].folder =
|
layers[REGION_LAYER_INVENTORIES].folder =
|
||||||
directory / fs::path("inventories");
|
directory / "inventories";
|
||||||
layers[REGION_LAYER_ENTITIES].folder = directory / fs::path("entities");
|
layers[REGION_LAYER_ENTITIES].folder = directory / "entities";
|
||||||
|
|
||||||
auto& blocksData = layers[REGION_LAYER_BLOCKS_DATA];
|
auto& blocksData = layers[REGION_LAYER_BLOCKS_DATA];
|
||||||
blocksData.folder = directory / fs::path("blocksdata");
|
blocksData.folder = directory / "blocksdata";
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldRegions::~WorldRegions() = default;
|
WorldRegions::~WorldRegions() = default;
|
||||||
@ -388,17 +388,17 @@ void WorldRegions::processRegion(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fs::path& WorldRegions::getRegionsFolder(RegionLayerIndex layerid) const {
|
const io::path& WorldRegions::getRegionsFolder(RegionLayerIndex layerid) const {
|
||||||
return layers[layerid].folder;
|
return layers[layerid].folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldRegions::getRegionFilePath(RegionLayerIndex layerid, int x, int z) const {
|
io::path WorldRegions::getRegionFilePath(RegionLayerIndex layerid, int x, int z) const {
|
||||||
return layers[layerid].getRegionFilePath(x, z);
|
return layers[layerid].getRegionFilePath(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldRegions::writeAll() {
|
void WorldRegions::writeAll() {
|
||||||
for (auto& layer : layers) {
|
for (auto& layer : layers) {
|
||||||
fs::create_directories(layer.folder);
|
io::create_directories(layer.folder);
|
||||||
layer.writeAll();
|
layer.writeAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -409,9 +409,9 @@ void WorldRegions::deleteRegion(RegionLayerIndex layerid, int x, int z) {
|
|||||||
throw std::runtime_error("region file is currently in use");
|
throw std::runtime_error("region file is currently in use");
|
||||||
}
|
}
|
||||||
auto file = layer.getRegionFilePath(x, z);
|
auto file = layer.getRegionFilePath(x, z);
|
||||||
if (fs::exists(file)) {
|
if (io::exists(file)) {
|
||||||
logger.info() << "remove region file " << file.u8string();
|
logger.info() << "remove region file " << file.string();
|
||||||
fs::remove(file);
|
io::remove(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <filesystem>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -19,8 +18,6 @@
|
|||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <glm/gtx/hash.hpp>
|
#include <glm/gtx/hash.hpp>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
inline constexpr uint REGION_HEADER_SIZE = 10;
|
inline constexpr uint REGION_HEADER_SIZE = 10;
|
||||||
|
|
||||||
inline constexpr uint REGION_SIZE_BIT = 5;
|
inline constexpr uint REGION_SIZE_BIT = 5;
|
||||||
@ -58,7 +55,7 @@ struct regfile {
|
|||||||
int version;
|
int version;
|
||||||
bool inUse = false;
|
bool inUse = false;
|
||||||
|
|
||||||
regfile(fs::path filename);
|
regfile(io::path filename);
|
||||||
regfile(const regfile&) = delete;
|
regfile(const regfile&) = delete;
|
||||||
|
|
||||||
std::unique_ptr<ubyte[]> read(int index, uint32_t& size, uint32_t& srcSize);
|
std::unique_ptr<ubyte[]> read(int index, uint32_t& size, uint32_t& srcSize);
|
||||||
@ -121,7 +118,7 @@ struct RegionsLayer {
|
|||||||
RegionLayerIndex layer;
|
RegionLayerIndex layer;
|
||||||
|
|
||||||
/// @brief Regions layer folder
|
/// @brief Regions layer folder
|
||||||
fs::path folder;
|
io::path folder;
|
||||||
|
|
||||||
compression::Method compression = compression::Method::NONE;
|
compression::Method compression = compression::Method::NONE;
|
||||||
|
|
||||||
@ -146,7 +143,7 @@ struct RegionsLayer {
|
|||||||
WorldRegion* getRegion(int x, int z);
|
WorldRegion* getRegion(int x, int z);
|
||||||
WorldRegion* getOrCreateRegion(int x, int z);
|
WorldRegion* getOrCreateRegion(int x, int z);
|
||||||
|
|
||||||
fs::path getRegionFilePath(int x, int z) const;
|
io::path getRegionFilePath(int x, int z) const;
|
||||||
|
|
||||||
/// @brief Get chunk data. Read from file if not loaded yet.
|
/// @brief Get chunk data. Read from file if not loaded yet.
|
||||||
/// @param x chunk x coord
|
/// @param x chunk x coord
|
||||||
@ -178,14 +175,14 @@ struct RegionsLayer {
|
|||||||
|
|
||||||
class WorldRegions {
|
class WorldRegions {
|
||||||
/// @brief World directory
|
/// @brief World directory
|
||||||
fs::path directory;
|
io::path directory;
|
||||||
|
|
||||||
RegionsLayer layers[REGION_LAYERS_COUNT] {};
|
RegionsLayer layers[REGION_LAYERS_COUNT] {};
|
||||||
public:
|
public:
|
||||||
bool generatorTestMode = false;
|
bool generatorTestMode = false;
|
||||||
bool doWriteLights = true;
|
bool doWriteLights = true;
|
||||||
|
|
||||||
WorldRegions(const fs::path& directory);
|
WorldRegions(const io::path& directory);
|
||||||
WorldRegions(const WorldRegions&) = delete;
|
WorldRegions(const WorldRegions&) = delete;
|
||||||
~WorldRegions();
|
~WorldRegions();
|
||||||
|
|
||||||
@ -241,9 +238,9 @@ public:
|
|||||||
/// @brief Get regions directory by layer index
|
/// @brief Get regions directory by layer index
|
||||||
/// @param layerid layer index
|
/// @param layerid layer index
|
||||||
/// @return directory path
|
/// @return directory path
|
||||||
const fs::path& getRegionsFolder(RegionLayerIndex layerid) const;
|
const io::path& getRegionsFolder(RegionLayerIndex layerid) const;
|
||||||
|
|
||||||
fs::path getRegionFilePath(RegionLayerIndex layerid, int x, int z) const;
|
io::path getRegionFilePath(RegionLayerIndex layerid, int x, int z) const;
|
||||||
|
|
||||||
/// @brief Write all region layers
|
/// @brief Write all region layers
|
||||||
void writeAll();
|
void writeAll();
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
TEST(lua_parsing, Tokenizer) {
|
TEST(lua_parsing, Tokenizer) {
|
||||||
auto filename = "../../res/scripts/stdlib.lua";
|
auto filename = "../../res/scripts/stdlib.lua";
|
||||||
auto source = io::read_string(std::filesystem::u8path(filename));
|
auto source = io::read_string(filename);
|
||||||
try {
|
try {
|
||||||
auto tokens = lua::tokenize(filename, source);
|
auto tokens = lua::tokenize(filename, source);
|
||||||
for (const auto& token : tokens) {
|
for (const auto& token : tokens) {
|
||||||
|
|||||||
@ -4,9 +4,7 @@
|
|||||||
#include "io/io.hpp"
|
#include "io/io.hpp"
|
||||||
|
|
||||||
TEST(VEC3, Decode) {
|
TEST(VEC3, Decode) {
|
||||||
auto file = std::filesystem::u8path(
|
io::path file = "res/models/block.vec3";
|
||||||
"res/models/block.vec3"
|
|
||||||
);
|
|
||||||
auto bytes = io::read_bytes_buffer(file);
|
auto bytes = io::read_bytes_buffer(file);
|
||||||
auto model = vec3::load(file.u8string(), bytes);
|
auto model = vec3::load(file.string(), bytes);
|
||||||
}
|
}
|
||||||
|
|||||||
14
test/io/path.cpp
Normal file
14
test/io/path.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "io/path.hpp"
|
||||||
|
|
||||||
|
TEST(Path, Path) {
|
||||||
|
io::path p("entry_point:path/file.ext");
|
||||||
|
EXPECT_EQ(p, "entry_point:path/file.ext");
|
||||||
|
EXPECT_EQ(p.pathPart(), "path/file.ext");
|
||||||
|
EXPECT_EQ(p.name(), "file.ext");
|
||||||
|
EXPECT_EQ(p.extension(), ".ext");
|
||||||
|
EXPECT_EQ(p.entryPoint(), "entry_point");
|
||||||
|
EXPECT_EQ(p / "child", "entry_point:path/file.ext/child");
|
||||||
|
EXPECT_EQ(p.parent(), "entry_point:path");
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user