diff --git a/res/layouts/inventory.xml b/res/layouts/inventory.xml
new file mode 100644
index 00000000..c33d57d6
--- /dev/null
+++ b/res/layouts/inventory.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/res/layouts/inventory.xml.lua b/res/layouts/inventory.xml.lua
new file mode 100644
index 00000000..532b9ee5
--- /dev/null
+++ b/res/layouts/inventory.xml.lua
@@ -0,0 +1,11 @@
+function on_open(inv)
+ print("OPEN", inv)
+end
+
+function on_close(inv)
+ print("CLOSE", inv)
+end
+
+function inventory_share_func(invid, slotid)
+ inventory.set(invid, slotid, 0, 0)
+end
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..09d28f55 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(fullpath) 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,7 @@ function dofile(path)
end
return _dofile(path)
end
+
+function pack.is_installed(packid)
+ return file.isfile(packid..":package.json")
+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/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/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 00ec8e0a..c03ebf4b 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,19 +42,25 @@ 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 world) {
+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");
@@ -58,12 +68,21 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, bool world) {
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");
- if (world) {
+ 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"/misc/moon.png", "misc/moon");
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun");
+
+ 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 +90,4 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, bool world) {
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 61a88b30..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