diff --git a/.github/workflows/appimage-wayland.yml b/.github/workflows/appimage-wayland.yml
new file mode 100644
index 00000000..f59902f7
--- /dev/null
+++ b/.github/workflows/appimage-wayland.yml
@@ -0,0 +1,42 @@
+name: C/C++ AppImage (wayland)
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build-appimage:
+
+ strategy:
+ matrix:
+ include:
+ - os: ubuntu-latest
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: 'true'
+ - name: install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y build-essential libglfw3-wayland libglfw3-dev libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev cmake squashfs-tools
+ sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua5.1.a
+ sudo ln -s /usr/include/luajit-2.1 /usr/include/lua
+ - name: configure
+ run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_APPDIR=1
+ - name: build
+ run: cmake --build build -t install
+ - name: Build AppImage
+ uses: AppImageCrafters/build-appimage-action@fe2205a4d6056be47051f7b1b3811106e9814910
+ env:
+ UPDATE_INFO: gh-releases-zsync|MihailRis|VoxelEngine-Cpp|latest|*x86_64.AppImage.zsync
+ with:
+ recipe: dev/AppImageBuilder.yml
+ - uses: actions/upload-artifact@v2
+ with:
+ name: AppImage
+ path: './*.AppImage*'
diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml
index 62f20563..f799077e 100644
--- a/.github/workflows/appimage.yml
+++ b/.github/workflows/appimage.yml
@@ -9,7 +9,12 @@ on:
jobs:
build-appimage:
- runs-on: ubuntu-20.04
+ strategy:
+ matrix:
+ include:
+ - os: ubuntu-latest
+
+ runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7ec5691b..b772fb72 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,7 +45,7 @@ if(MSVC)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /source-charset:UTF-8")
else()
- target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -lstdc++fs
+ target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra
# additional warnings
-Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wundef
@@ -114,7 +114,7 @@ if(UNIX)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie -lstdc++fs")
endif()
include_directories(${LUA_INCLUDE_DIR})
diff --git a/res/content/base/package.json b/res/content/base/package.json
index bd8c1c2a..249dd4ee 100644
--- a/res/content/base/package.json
+++ b/res/content/base/package.json
@@ -1,6 +1,6 @@
{
"id": "base",
"title": "Base",
- "version": "0.18",
+ "version": "0.19",
"description": "basic content package"
}
diff --git a/res/content/base/textures/blocks/dirt.png b/res/content/base/textures/blocks/dirt.png
index 6239e67c..9fc51ad8 100644
Binary files a/res/content/base/textures/blocks/dirt.png and b/res/content/base/textures/blocks/dirt.png differ
diff --git a/res/content/base/textures/blocks/flower.png b/res/content/base/textures/blocks/flower.png
index 38f070eb..a69626de 100644
Binary files a/res/content/base/textures/blocks/flower.png and b/res/content/base/textures/blocks/flower.png differ
diff --git a/res/content/base/textures/blocks/grass_side.png b/res/content/base/textures/blocks/grass_side.png
index 802c1a87..553bd8b4 100644
Binary files a/res/content/base/textures/blocks/grass_side.png and b/res/content/base/textures/blocks/grass_side.png differ
diff --git a/res/content/base/textures/blocks/leaves.png b/res/content/base/textures/blocks/leaves.png
index 861fbcb7..3beaf7ab 100644
Binary files a/res/content/base/textures/blocks/leaves.png and b/res/content/base/textures/blocks/leaves.png differ
diff --git a/res/content/base/textures/blocks/stone.png b/res/content/base/textures/blocks/stone.png
index 5214e3e1..53620aa1 100644
Binary files a/res/content/base/textures/blocks/stone.png and b/res/content/base/textures/blocks/stone.png differ
diff --git a/res/layouts/inventory.xml b/res/layouts/inventory.xml
new file mode 100644
index 00000000..6d2fc761
--- /dev/null
+++ b/res/layouts/inventory.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/res/layouts/inventory.xml.lua b/res/layouts/inventory.xml.lua
new file mode 100644
index 00000000..bc3fc5d2
--- /dev/null
+++ b/res/layouts/inventory.xml.lua
@@ -0,0 +1,3 @@
+function inventory_share_func(invid, slotid)
+ inventory.set(invid, slotid, 0, 0)
+end
diff --git a/res/modules/document.lua b/res/modules/document.lua
new file mode 100644
index 00000000..e69de29b
diff --git a/res/modules/toml.lua b/res/modules/toml.lua
new file mode 100644
index 00000000..fb082e75
--- /dev/null
+++ b/res/modules/toml.lua
@@ -0,0 +1,65 @@
+-- TOML serialization module
+local toml = {}
+
+-- Convert table to TOML
+function toml.serialize(tb, isinner)
+ local text = ""
+ for k, v in pairs(tb) do
+ local tp = type(v)
+ if tp ~= "table" then
+ text = text..k.." = "
+ if tp == "string" then
+ text = text..string.format("%q", v)
+ else
+ text = text..tostring(v)
+ end
+ text = text.."\n"
+ end
+ end
+ for k, v in pairs(tb) do
+ local tp = type(v)
+ if tp == "table" then
+ if isinner then
+ error("only one level of subtables supported")
+ end
+ text = text.."["..k.."]\n"..toml.serialize(v).."\n"
+ end
+ end
+ return text
+end
+
+-- Parse TOML to new table
+function toml.deserialize(s)
+ local output = {}
+ local current = output
+ local lines = {}
+ for line in string.gmatch(s, "[^\r\n]+") do
+ line = string.gsub(line, "%s+", "")
+ table.insert(lines, line)
+ end
+ for i = 1,#lines do
+ local s = lines[i]
+ if string.sub(s, 1, 1) == "[" then
+ local section = s.sub(s, 2, #s-1)
+ current = {}
+ output[section] = current
+ else
+ for k, v in string.gmatch(s, "(%w+)=(.+)" ) do
+ v = string.gsub(v, "%s+", "")
+ if v.sub(v, 1, 1) == "\"" then
+ current[k] = v.sub(v, 2, #v-1)
+ elseif v == "true" or v == "false" then
+ current[k] = v == "true"
+ end
+
+ local num = tonumber(v)
+ if num ~= nil then
+ current[k] = num
+ end
+ end
+ end
+ end
+ return output
+end
+
+return toml
diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua
index ace88536..370d4eef 100644
--- a/res/scripts/stdlib.lua
+++ b/res/scripts/stdlib.lua
@@ -37,10 +37,14 @@ function load_script(path, nocache)
if not nocache and __cached_scripts[fullpath] ~= nil then
return __cached_results[fullpath]
end
- local script = loadfile(fullpath)
- if script == nil then
+ if not file.isfile(path) then
error("script '"..filename.."' not found in '"..packname.."'")
end
+
+ local script, err = loadfile(fullpath)
+ if script == nil then
+ error(err)
+ end
local result = script()
if not nocache then
__cached_scripts[fullpath] = script
@@ -49,6 +53,16 @@ function load_script(path, nocache)
return result
end
+function require(path)
+ local prefix, file = parse_path(path)
+ return load_script(prefix..":modules/"..file..".lua")
+end
+
+function __reset_scripts_cache()
+ __cached_scripts = {}
+ __cached_results = {}
+end
+
function sleep(timesec)
local start = time.uptime()
while time.uptime() - start < timesec do
@@ -73,3 +87,50 @@ function dofile(path)
end
return _dofile(path)
end
+
+function pack.is_installed(packid)
+ return file.isfile(packid..":package.json")
+end
+
+vec2_mt = {}
+function vec2_mt.__tostring(self)
+ return "vec2("..self[1]..", "..self[2]..")"
+end
+
+vec3_mt = {}
+function vec3_mt.__tostring(self)
+ return "vec3("..self[1]..", "..self[2]..", "..self[3]..")"
+end
+
+vec4_mt = {}
+function vec4_mt.__tostring(self)
+ return "vec4("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")"
+end
+
+color_mt = {}
+function color_mt.__tostring(self)
+ return "rgba("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")"
+end
+
+-- class designed for simple UI-nodes access via properties syntax
+local Element = {}
+function Element.new(docname, name)
+ return setmetatable({docname=docname, name=name}, {
+ __index=function(self, k)
+ return gui.getattr(self.docname, self.name, k)
+ end,
+ __newindex=function(self, k, v)
+ gui.setattr(self.docname, self.name, k, v)
+ end
+ })
+end
+
+-- the engine automatically creates an instance for every ui document (layout)
+Document = {}
+function Document.new(docname)
+ return setmetatable({name=docname}, {
+ __index=function(self, k)
+ return Element.new(self.name, k)
+ end
+ })
+end
diff --git a/res/scripts/world.lua b/res/scripts/world.lua
index e69de29b..964100e7 100644
--- a/res/scripts/world.lua
+++ b/res/scripts/world.lua
@@ -0,0 +1,3 @@
+-- use for engine development tests
+-- must be empty in release
+-- must not be modified by content-packs
diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv
index f368328d..e59839a0 100644
--- a/res/shaders/main.glslv
+++ b/res/shaders/main.glslv
@@ -26,6 +26,7 @@ uniform float u_torchlightDistance;
void main(){
vec3 pos3d = (u_model * vec4(v_position, 1.0)).xyz-u_cameraPos.xyz;
vec4 modelpos = u_model * vec4(v_position, 1.0);
+ modelpos.y -= pow(length(pos3d.xz)*0.002, 3.0);
vec4 viewmodelpos = u_view * modelpos;
vec4 decomp_light = decompress_light(v_light);
vec3 light = decomp_light.rgb;
diff --git a/res/texts/be_BY.txt b/res/texts/be_BY.txt
index 5ca3dcc1..0e574fd4 100644
--- a/res/texts/be_BY.txt
+++ b/res/texts/be_BY.txt
@@ -34,6 +34,7 @@ settings.Load Speed=Хуткасць Загрузкі
settings.Fog Curve=Крывая Туману
settings.Backlight=Падсветка
settings.V-Sync=Вертыкальная Сінхранізацыя
+settings.Camera Shaking=Труска Камеры
settings.FOV=Поле Зроку
settings.Mouse Sensitivity=Адчувальнасць Мышы
diff --git a/res/texts/fi_FI.txt b/res/texts/fi_FI.txt
index 4da41a1c..124a2956 100644
--- a/res/texts/fi_FI.txt
+++ b/res/texts/fi_FI.txt
@@ -13,8 +13,8 @@ menu.New World = Uusi Maailma
menu.Quit=Poistu
menu.Continue=Jatka
menu.Save and Quit to Menu=Tallenna ja poistu valikkoon
-menu.missing-content=Puuttuu jotkut lisäosat!
-menu.Content Error=Sisältövirhe!
+menu.missing-content=Puuttuu lisäosia!
+menu.Content Error=Lisäosa virhe!
menu.Controls=Ohjaus
menu.Back to Main Menu=Takaisin Valikoon
menu.Settings=Asetukset
diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt
index 65085d46..71fabbb7 100644
--- a/res/texts/ru_RU.txt
+++ b/res/texts/ru_RU.txt
@@ -34,6 +34,7 @@ settings.Load Speed=Скорость Загрузки
settings.Fog Curve=Кривая Тумана
settings.Backlight=Подсветка
settings.V-Sync=Вертикальная Синхронизация
+settings.Camera Shaking=Тряска Камеры
settings.FOV=Поле Зрения
settings.Mouse Sensitivity=Чувствительность Мыши
diff --git a/res/textures/gui/crosshair.png b/res/textures/gui/crosshair.png
new file mode 100644
index 00000000..7010266b
Binary files /dev/null and b/res/textures/gui/crosshair.png differ
diff --git a/res/textures/gui/error.png b/res/textures/gui/error.png
new file mode 100644
index 00000000..5651ac6c
Binary files /dev/null and b/res/textures/gui/error.png differ
diff --git a/res/textures/gui/warning.png b/res/textures/gui/warning.png
new file mode 100644
index 00000000..7dbbd087
Binary files /dev/null and b/res/textures/gui/warning.png differ
diff --git a/src/assets/Assets.cpp b/src/assets/Assets.cpp
index c13f3da0..5183cca2 100644
--- a/src/assets/Assets.cpp
+++ b/src/assets/Assets.cpp
@@ -4,6 +4,8 @@
#include "../graphics/Shader.h"
#include "../graphics/Atlas.h"
#include "../graphics/Font.h"
+#include "../frontend/UiDocument.h"
+#include "../logic/scripting/scripting.h"
Assets::~Assets() {
}
@@ -62,6 +64,17 @@ void Assets::store(const TextureAnimation& animation) {
animations.emplace_back(animation);
}
+UiDocument* Assets::getLayout(std::string name) const {
+ auto found = layouts.find(name);
+ if (found == layouts.end())
+ return nullptr;
+ return found->second.get();
+}
+
+void Assets::store(UiDocument* layout, std::string name) {
+ layouts[name].reset(layout);
+}
+
void Assets::extend(const Assets& assets) {
for (auto entry : assets.textures) {
textures[entry.first] = entry.second;
@@ -75,6 +88,9 @@ void Assets::extend(const Assets& assets) {
for (auto entry : assets.atlases) {
atlases[entry.first] = entry.second;
}
+ for (auto entry : assets.layouts) {
+ layouts[entry.first] = entry.second;
+ }
animations.clear();
for (auto entry : assets.animations) {
animations.emplace_back(entry);
diff --git a/src/assets/Assets.h b/src/assets/Assets.h
index 6df72ac4..87e94380 100644
--- a/src/assets/Assets.h
+++ b/src/assets/Assets.h
@@ -12,12 +12,20 @@ class Texture;
class Shader;
class Font;
class Atlas;
+class UiDocument;
+
+struct LayoutCfg {
+ int env;
+
+ LayoutCfg(int env) : env(env) {}
+};
class Assets {
std::unordered_map> textures;
std::unordered_map> shaders;
std::unordered_map> fonts;
std::unordered_map> atlases;
+ std::unordered_map> layouts;
std::vector animations;
public:
~Assets();
@@ -36,6 +44,9 @@ public:
const std::vector& getAnimations();
void store(const TextureAnimation& animation);
+ UiDocument* getLayout(std::string name) const;
+ void store(UiDocument* layout, std::string name);
+
void extend(const Assets& assets);
};
diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp
index 9ef4696d..2298904a 100644
--- a/src/assets/AssetsLoader.cpp
+++ b/src/assets/AssetsLoader.cpp
@@ -8,20 +8,24 @@
#include "../constants.h"
#include "../files/engine_paths.h"
-
-using std::filesystem::path;
-using std::unique_ptr;
+#include "../content/Content.h"
+#include "../logic/scripting/scripting.h"
AssetsLoader::AssetsLoader(Assets* assets, const ResPaths* paths)
: assets(assets), paths(paths) {
+ addLoader(ASSET_SHADER, assetload::shader);
+ addLoader(ASSET_TEXTURE, assetload::texture);
+ addLoader(ASSET_FONT, assetload::font);
+ addLoader(ASSET_ATLAS, assetload::atlas);
+ addLoader(ASSET_LAYOUT, assetload::layout);
}
void AssetsLoader::addLoader(int tag, aloader_func func) {
loaders[tag] = func;
}
-void AssetsLoader::add(int tag, const std::string filename, const std::string alias) {
- entries.push(aloader_entry{ tag, filename, alias });
+void AssetsLoader::add(int tag, const std::string filename, const std::string alias, std::shared_ptr settings) {
+ entries.push(aloader_entry{ tag, filename, alias, settings});
}
bool AssetsLoader::hasNext() const {
@@ -38,32 +42,48 @@ bool AssetsLoader::loadNext() {
return false;
}
aloader_func loader = found->second;
- bool status = loader(assets, paths, entry.filename, entry.alias);
+ bool status = loader(*this, assets, paths, entry.filename, entry.alias, entry.config);
entries.pop();
return status;
}
-void AssetsLoader::createDefaults(AssetsLoader& loader) {
- loader.addLoader(ASSET_SHADER, assetload::shader);
- loader.addLoader(ASSET_TEXTURE, assetload::texture);
- loader.addLoader(ASSET_FONT, assetload::font);
- loader.addLoader(ASSET_ATLAS, assetload::atlas);
+void addLayouts(int env, const std::string& prefix, const fs::path& folder, AssetsLoader& loader) {
+ if (!fs::is_directory(folder)) {
+ return;
+ }
+ for (auto& entry : fs::directory_iterator(folder)) {
+ const fs::path file = entry.path();
+ if (file.extension().u8string() != ".xml")
+ continue;
+ std::string name = prefix+":"+file.stem().u8string();
+ loader.add(ASSET_LAYOUT, file.u8string(), name, std::make_shared(env));
+ }
}
-void AssetsLoader::addDefaults(AssetsLoader& loader, bool allAssets) {
- if (allAssets) {
- loader.add(ASSET_SHADER, SHADERS_FOLDER"/main", "main");
- loader.add(ASSET_SHADER, SHADERS_FOLDER"/lines", "lines");
- loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui", "ui");
+void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
+ loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal");
+ loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui", "ui");
+ loader.add(ASSET_SHADER, SHADERS_FOLDER"/main", "main");
+ loader.add(ASSET_SHADER, SHADERS_FOLDER"/lines", "lines");
+ loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/menubg.png", "gui/menubg");
+ loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/delete_icon.png", "gui/delete_icon");
+ loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/no_icon.png", "gui/no_icon");
+ loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/warning.png", "gui/warning");
+ loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/error.png", "gui/error");
+ if (content) {
loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui3d", "ui3d");
loader.add(ASSET_SHADER, SHADERS_FOLDER"/background", "background");
loader.add(ASSET_SHADER, SHADERS_FOLDER"/skybox_gen", "skybox_gen");
- loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/menubg.png", "gui/menubg");
- loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/delete_icon.png", "gui/delete_icon");
- loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/no_icon.png", "gui/no_icon");
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/moon.png", "misc/moon");
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun");
- loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal");
+ loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/crosshair.png", "gui/crosshair");
+
+ addLayouts(0, "core", loader.getPaths()->getMainRoot()/fs::path("layouts"), loader);
+ for (auto& pack : content->getPacks()) {
+ auto& info = pack->getInfo();
+ fs::path folder = info.folder / fs::path("layouts");
+ addLayouts(pack->getEnvironment()->getId(), info.id, folder, loader);
+ }
}
loader.add(ASSET_ATLAS, TEXTURES_FOLDER"/blocks", "blocks");
loader.add(ASSET_ATLAS, TEXTURES_FOLDER"/items", "items");
@@ -71,4 +91,4 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, bool allAssets) {
const ResPaths* AssetsLoader::getPaths() const {
return paths;
-}
\ No newline at end of file
+}
diff --git a/src/assets/AssetsLoader.h b/src/assets/AssetsLoader.h
index 13ea12fa..de401846 100644
--- a/src/assets/AssetsLoader.h
+++ b/src/assets/AssetsLoader.h
@@ -2,6 +2,7 @@
#define ASSETS_ASSETS_LOADER_H
#include
+#include
#include
#include