mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-13 06:51:51 +00:00
Merge branch 'main' into volume-renderer
This commit is contained in:
commit
d9a7afad05
42 changed files with 539 additions and 196 deletions
|
|
@ -5,6 +5,13 @@ A library for working with audio/visual assets.
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
-- Requests background texture loading
|
||||||
|
assets.request_texture(
|
||||||
|
-- Image file
|
||||||
|
filename: string,
|
||||||
|
-- Texture name after loading
|
||||||
|
name: string,
|
||||||
|
)
|
||||||
-- Loads a texture
|
-- Loads a texture
|
||||||
assets.load_texture(
|
assets.load_texture(
|
||||||
-- Array of bytes of an image file
|
-- Array of bytes of an image file
|
||||||
|
|
|
||||||
|
|
@ -167,10 +167,11 @@ Properties:
|
||||||
|
|
||||||
Properties:
|
Properties:
|
||||||
|
|
||||||
| Name | Type | Read | Write | Description |
|
| Name | Type | Read | Write | Description |
|
||||||
| ------ | ------ | ---- | ----- | ---------------- |
|
| -------- | ------ | ---- | ----- | ---------------- |
|
||||||
| src | string | yes | yes | texture name |
|
| src | string | yes | yes | texture name |
|
||||||
| region | vec4 | yes | yes | image sub-region |
|
| fallback | string | yes | yes | fallback texture |
|
||||||
|
| region | vec4 | yes | yes | image sub-region |
|
||||||
|
|
||||||
## Canvas
|
## Canvas
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ Inner text is a button text.
|
||||||
|
|
||||||
- `src` - name of an image stored in textures folder. Extension is not specified. Type: string.
|
- `src` - name of an image stored in textures folder. Extension is not specified. Type: string.
|
||||||
Example: *gui/error*
|
Example: *gui/error*
|
||||||
|
- `fallback` - a fallback texture displayed when the main texture is missing / loading.
|
||||||
- `region` - image region x1, y1, x2, y2 from 0.0, 0.0 (upper left corner), 1.0, 1.0 (lower right corner)
|
- `region` - image region x1, y1, x2, y2 from 0.0, 0.0 (upper left corner), 1.0, 1.0 (lower right corner)
|
||||||
|
|
||||||
## *canvas*
|
## *canvas*
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,14 @@
|
||||||
## Функции
|
## Функции
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
-- Запрашивает фоновую загрузку текстуры
|
||||||
|
assets.request_texture(
|
||||||
|
-- Файл изображения
|
||||||
|
filename: string,
|
||||||
|
-- Имя текстуры после загрузки
|
||||||
|
name: string,
|
||||||
|
)
|
||||||
|
|
||||||
-- Загружает текстуру
|
-- Загружает текстуру
|
||||||
assets.load_texture(
|
assets.load_texture(
|
||||||
-- Массив байт файла изображения
|
-- Массив байт файла изображения
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,7 @@ document["worlds-panel"]:clear()
|
||||||
| Название | Тип | Чтение | Запись | Описание |
|
| Название | Тип | Чтение | Запись | Описание |
|
||||||
| -------- | ------ | ------ | ------ | ---------------------- |
|
| -------- | ------ | ------ | ------ | ---------------------- |
|
||||||
| src | string | да | да | отображаемая текстура |
|
| src | string | да | да | отображаемая текстура |
|
||||||
|
| fallback | string | да | да | резервная текстура |
|
||||||
| region | vec4 | да | да | под-регион изображения |
|
| region | vec4 | да | да | под-регион изображения |
|
||||||
|
|
||||||
## Холст (canvas)
|
## Холст (canvas)
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@
|
||||||
## Изображение - *image*
|
## Изображение - *image*
|
||||||
|
|
||||||
- `src` - имя изображения в папке textures без указания расширения. Тип: строка. Например `gui/error`
|
- `src` - имя изображения в папке textures без указания расширения. Тип: строка. Например `gui/error`
|
||||||
|
- `fallback` - резервная текстура, отображаемая при отсутствии / фоновой загрузке основной
|
||||||
- `region` - под-регион изображения x1, y1, x2, y2 от 0.0, 0.0 (левый верхний угол), 1.0, 1.0 (правый нижний угол)
|
- `region` - под-регион изображения x1, y1, x2, y2 от 0.0, 0.0 (левый верхний угол), 1.0, 1.0 (правый нижний угол)
|
||||||
|
|
||||||
## Холст - *canvas*
|
## Холст - *canvas*
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ function ores.place(placements, x, z, w, d, seed, hmap, chunk_height)
|
||||||
for i=1,count do
|
for i=1,count do
|
||||||
local sx = math.random() * w
|
local sx = math.random() * w
|
||||||
local sz = math.random() * d
|
local sz = math.random() * d
|
||||||
local sy = math.random() * (chunk_height * 0.5)
|
local sy = math.random() * (chunk_height * 0.5) + 6
|
||||||
if sy < hmap:at(sx, sz) * chunk_height - 6 then
|
if sy < hmap:at(sx, sz) * chunk_height - 6 then
|
||||||
table.insert(placements, {ore.struct, {sx, sy, sz}, math.random()*4, -1})
|
table.insert(placements, {ore.struct, {sx, sy, sz}, math.random()*4, -1})
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,9 @@ local function include(id, is_include)
|
||||||
end
|
end
|
||||||
|
|
||||||
function apply()
|
function apply()
|
||||||
core.reconfig_packs(add_packs, rem_packs)
|
time.post_runnable(function ()
|
||||||
|
app.reconfig_packs(add_packs, rem_packs)
|
||||||
|
end)
|
||||||
if mode ~= "world" then
|
if mode ~= "world" then
|
||||||
menu:back()
|
menu:back()
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,5 @@
|
||||||
<label ifnot='%{error}' pos='80,28' size='355,50' multiline='true' color='#FFFFFFB2'>
|
<label ifnot='%{error}' pos='80,28' size='355,50' multiline='true' color='#FFFFFFB2'>
|
||||||
%{description}
|
%{description}
|
||||||
</label>
|
</label>
|
||||||
<image pos='8,8' src='%{icon}' size='64'/>
|
<image pos='8,8' src='%{icon}' fallback='gui/no_icon' size='64'/>
|
||||||
</container>
|
</container>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
hover-color='#162B3399'
|
hover-color='#162B3399'
|
||||||
onclick='app.open_world("%{name}")'
|
onclick='app.open_world("%{name}")'
|
||||||
>
|
>
|
||||||
<image pos='1' src='%{icon}' size='96,64'></image>
|
<image pos='1' src='%{icon}' fallback='gui/no_world_icon' size='96,64'></image>
|
||||||
<label pos='104,8'>%{name}</label>
|
<label pos='104,8'>%{name}</label>
|
||||||
<button margin='4'
|
<button margin='4'
|
||||||
gravity='center-right'
|
gravity='center-right'
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ function tb_frame_tostring(frame)
|
||||||
end
|
end
|
||||||
|
|
||||||
local __vc__app_script_coroutine
|
local __vc__app_script_coroutine
|
||||||
|
local __vc__is_post_runnable = false
|
||||||
|
|
||||||
local function complete_app_lib(app)
|
local function complete_app_lib(app)
|
||||||
local __app_load_content = app.load_content
|
local __app_load_content = app.load_content
|
||||||
|
|
@ -44,6 +45,10 @@ local function complete_app_lib(app)
|
||||||
app.tick = __app_tick
|
app.tick = __app_tick
|
||||||
|
|
||||||
local function call_in_app_script_co(func, ...)
|
local function call_in_app_script_co(func, ...)
|
||||||
|
if __vc__is_post_runnable then
|
||||||
|
func(...)
|
||||||
|
return
|
||||||
|
end
|
||||||
local running = coroutine.running()
|
local running = coroutine.running()
|
||||||
if not running or running ~= __vc__app_script_coroutine then
|
if not running or running ~= __vc__app_script_coroutine then
|
||||||
error("content must be reload in application script coroutine")
|
error("content must be reload in application script coroutine")
|
||||||
|
|
@ -513,7 +518,7 @@ local fn_audio_reset_fetch_buffer = audio.__reset_fetch_buffer
|
||||||
audio.__reset_fetch_buffer = nil
|
audio.__reset_fetch_buffer = nil
|
||||||
core.get_core_token = audio.input.__get_core_token
|
core.get_core_token = audio.input.__get_core_token
|
||||||
|
|
||||||
function __process_post_runnables()
|
local function __vc__process_post_runnables()
|
||||||
if #__post_runnables then
|
if #__post_runnables then
|
||||||
for _, func in ipairs(__post_runnables) do
|
for _, func in ipairs(__post_runnables) do
|
||||||
local status, result = xpcall(func, __vc__error)
|
local status, result = xpcall(func, __vc__error)
|
||||||
|
|
@ -547,6 +552,15 @@ function __process_post_runnables()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function __process_post_runnables()
|
||||||
|
__vc__is_post_runnable = true
|
||||||
|
local success, err = pcall(__vc__process_post_runnables)
|
||||||
|
if not success then
|
||||||
|
debug.error("an error ocurred while processing post-runnables: ".. err)
|
||||||
|
end
|
||||||
|
__vc__is_post_runnable = false
|
||||||
|
end
|
||||||
|
|
||||||
function time.post_runnable(runnable)
|
function time.post_runnable(runnable)
|
||||||
table.insert(__post_runnables, runnable)
|
table.insert(__post_runnables, runnable)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -319,28 +319,31 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetsLoader::loadExternalTexture(
|
bool AssetsLoader::loadExternalTexture(
|
||||||
Assets* assets,
|
AssetsLoader& loader,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<io::path>& alternatives
|
const std::vector<io::path>& alternatives
|
||||||
) {
|
) {
|
||||||
if (assets->get<Texture>(name) != nullptr) {
|
if (loader.getAssets().get<Texture>(name) != nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (auto& path : alternatives) {
|
for (auto& path : alternatives) {
|
||||||
if (io::exists(path)) {
|
if (io::exists(path)) {
|
||||||
try {
|
loader.add(
|
||||||
auto image = imageio::read(path);
|
AssetType::TEXTURE,
|
||||||
assets->store(Texture::from(image.get()), name);
|
(path.parent() / path.stem()).string(),
|
||||||
return true;
|
name,
|
||||||
} catch (const std::exception& err) {
|
nullptr
|
||||||
logger.error() << "error while loading external "
|
);
|
||||||
<< path.string() << ": " << err.what();
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assets& AssetsLoader::getAssets() {
|
||||||
|
return assets;
|
||||||
|
}
|
||||||
|
|
||||||
Engine& AssetsLoader::getEngine() {
|
Engine& AssetsLoader::getEngine() {
|
||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
@ -368,14 +371,24 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<Task> AssetsLoader::startTask(runnable onDone) {
|
std::shared_ptr<Task> AssetsLoader::startTask(runnable onDone, int maxWorkers) {
|
||||||
auto pool =
|
auto pool =
|
||||||
std::make_shared<util::ThreadPool<aloader_entry, assetload::postfunc>>(
|
std::make_shared<util::ThreadPool<aloader_entry, assetload::postfunc>>(
|
||||||
"assets-loader-pool",
|
"assets-loader-pool",
|
||||||
[=]() { return std::make_unique<LoaderWorker>(this); },
|
[=]() { return std::make_unique<LoaderWorker>(this); },
|
||||||
[this](assetload::postfunc&& func) { func(&assets); }
|
[this](const assetload::postfunc& func) { func(&assets); },
|
||||||
|
maxWorkers
|
||||||
);
|
);
|
||||||
pool->setOnComplete(std::move(onDone));
|
pool->setOnComplete(std::move(onDone));
|
||||||
|
pool->setJobsSource([this]() -> std::optional<aloader_entry> {
|
||||||
|
if (entries.empty()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
aloader_entry entry = std::move(entries.front());
|
||||||
|
entries.pop();
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
|
||||||
while (!entries.empty()) {
|
while (!entries.empty()) {
|
||||||
aloader_entry entry = std::move(entries.front());
|
aloader_entry entry = std::move(entries.front());
|
||||||
entries.pop();
|
entries.pop();
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ public:
|
||||||
/// @throws assetload::error
|
/// @throws assetload::error
|
||||||
void loadNext();
|
void loadNext();
|
||||||
|
|
||||||
std::shared_ptr<Task> startTask(runnable onDone);
|
std::shared_ptr<Task> startTask(runnable onDone, int maxWorkers);
|
||||||
|
|
||||||
const ResPaths& getPaths() const;
|
const ResPaths& getPaths() const;
|
||||||
aloader_func getLoader(AssetType tag);
|
aloader_func getLoader(AssetType tag);
|
||||||
|
|
@ -124,10 +124,11 @@ public:
|
||||||
static void addDefaults(AssetsLoader& loader, const Content* content);
|
static void addDefaults(AssetsLoader& loader, const Content* content);
|
||||||
|
|
||||||
static bool loadExternalTexture(
|
static bool loadExternalTexture(
|
||||||
Assets* assets,
|
AssetsLoader& loader,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<io::path>& alternatives
|
const std::vector<io::path>& alternatives
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Assets& getAssets();
|
||||||
Engine& getEngine();
|
Engine& getEngine();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,8 @@ static void load_script(const Content& content, T& def) {
|
||||||
def.name,
|
def.name,
|
||||||
scriptfile,
|
scriptfile,
|
||||||
def.scriptFile,
|
def.scriptFile,
|
||||||
def.rt.funcsset
|
def.rt.funcsset,
|
||||||
|
def.rt.eventNames
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
92
src/engine/AssetsManagement.cpp
Normal file
92
src/engine/AssetsManagement.cpp
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include "AssetsManagement.hpp"
|
||||||
|
|
||||||
|
#include "assets/AssetsLoader.hpp"
|
||||||
|
#include "coders/GLSLExtension.hpp"
|
||||||
|
#include "content/Content.hpp"
|
||||||
|
#include "debug/Logger.hpp"
|
||||||
|
#include "engine/Engine.hpp"
|
||||||
|
#include "EnginePaths.hpp"
|
||||||
|
#include "graphics/core/Shader.hpp"
|
||||||
|
#include "graphics/render/ModelsGenerator.hpp"
|
||||||
|
#include "graphics/ui/GUI.hpp"
|
||||||
|
|
||||||
|
static debug::Logger logger("assets-management");
|
||||||
|
|
||||||
|
AssetsManagement::AssetsManagement(Engine& engine)
|
||||||
|
: engine(engine), settings(engine.getSettings()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetsManagement::~AssetsManagement() {
|
||||||
|
finishBackgroundLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Assets* AssetsManagement::getStorage() const {
|
||||||
|
return assets.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assets* AssetsManagement::getStorage() {
|
||||||
|
return assets.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetsLoader& AssetsManagement::acquireBackgroundLoader() {
|
||||||
|
if (backgroundLoader) {
|
||||||
|
return *backgroundLoader;
|
||||||
|
}
|
||||||
|
if (assets == nullptr) {
|
||||||
|
throw std::runtime_error("no assets storage available");
|
||||||
|
}
|
||||||
|
backgroundLoader = std::make_unique<AssetsLoader>(
|
||||||
|
engine, *assets, engine.getResPaths()
|
||||||
|
);
|
||||||
|
backgroundLoaderTask = backgroundLoader->startTask(
|
||||||
|
nullptr, settings.system.maxBgAssetLoaders.get()
|
||||||
|
);
|
||||||
|
return *backgroundLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManagement::loadAssets(Content* content) {
|
||||||
|
finishBackgroundLoader();
|
||||||
|
|
||||||
|
const auto& paths = engine.getPaths();
|
||||||
|
logger.info() << "loading assets";
|
||||||
|
Shader::preprocessor->setPaths(&paths.resPaths);
|
||||||
|
|
||||||
|
auto new_assets = std::make_unique<Assets>();
|
||||||
|
AssetsLoader loader(engine, *new_assets, paths.resPaths);
|
||||||
|
AssetsLoader::addDefaults(loader, content);
|
||||||
|
|
||||||
|
// no need
|
||||||
|
// correct log messages order is more useful
|
||||||
|
// todo: before setting to true, check if GLSLExtension thread safe
|
||||||
|
bool threading = false; // look at three upper lines
|
||||||
|
if (threading) {
|
||||||
|
auto task = loader.startTask(
|
||||||
|
[=]() {}, 0
|
||||||
|
);
|
||||||
|
task->waitForEnd();
|
||||||
|
} else {
|
||||||
|
while (loader.hasNext()) {
|
||||||
|
loader.loadNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assets = std::move(new_assets);
|
||||||
|
if (content) {
|
||||||
|
ModelsGenerator::prepare(*content, *assets);
|
||||||
|
}
|
||||||
|
assets->setup();
|
||||||
|
engine.getGUI().onAssetsLoad(assets.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManagement::update() {
|
||||||
|
if (backgroundLoaderTask) {
|
||||||
|
backgroundLoaderTask->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManagement::finishBackgroundLoader() {
|
||||||
|
if (backgroundLoaderTask == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
backgroundLoaderTask.reset();
|
||||||
|
backgroundLoader.reset();
|
||||||
|
}
|
||||||
33
src/engine/AssetsManagement.hpp
Normal file
33
src/engine/AssetsManagement.hpp
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "assets/Assets.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class AssetsLoader;
|
||||||
|
class Engine;
|
||||||
|
class Content;
|
||||||
|
class Task;
|
||||||
|
struct EngineSettings;
|
||||||
|
|
||||||
|
class AssetsManagement final {
|
||||||
|
public:
|
||||||
|
AssetsManagement(Engine& engine);
|
||||||
|
~AssetsManagement();
|
||||||
|
|
||||||
|
void loadAssets(Content* content);
|
||||||
|
void update();
|
||||||
|
|
||||||
|
Assets* getStorage();
|
||||||
|
const Assets* getStorage() const;
|
||||||
|
|
||||||
|
AssetsLoader& acquireBackgroundLoader();
|
||||||
|
private:
|
||||||
|
void finishBackgroundLoader();
|
||||||
|
|
||||||
|
Engine& engine;
|
||||||
|
const EngineSettings& settings;
|
||||||
|
std::unique_ptr<Assets> assets;
|
||||||
|
std::unique_ptr<AssetsLoader> backgroundLoader;
|
||||||
|
std::shared_ptr<Task> backgroundLoaderTask;
|
||||||
|
};
|
||||||
|
|
@ -4,47 +4,45 @@
|
||||||
#define GLEW_STATIC
|
#define GLEW_STATIC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "debug/Logger.hpp"
|
#include "AssetsManagement.hpp"
|
||||||
#include "assets/AssetsLoader.hpp"
|
|
||||||
#include "audio/audio.hpp"
|
#include "audio/audio.hpp"
|
||||||
|
#include "coders/commons.hpp"
|
||||||
#include "coders/GLSLExtension.hpp"
|
#include "coders/GLSLExtension.hpp"
|
||||||
#include "coders/toml.hpp"
|
#include "coders/toml.hpp"
|
||||||
#include "coders/commons.hpp"
|
|
||||||
#include "devtools/Editor.hpp"
|
|
||||||
#include "devtools/Project.hpp"
|
|
||||||
#include "devtools/DebuggingServer.hpp"
|
|
||||||
#include "content/ContentControl.hpp"
|
#include "content/ContentControl.hpp"
|
||||||
#include "core_defs.hpp"
|
#include "core_defs.hpp"
|
||||||
#include "io/io.hpp"
|
#include "debug/Logger.hpp"
|
||||||
#include "io/settings_io.hpp"
|
#include "devtools/DebuggingServer.hpp"
|
||||||
|
#include "devtools/Editor.hpp"
|
||||||
|
#include "devtools/Project.hpp"
|
||||||
|
#include "EnginePaths.hpp"
|
||||||
#include "frontend/locale.hpp"
|
#include "frontend/locale.hpp"
|
||||||
#include "frontend/menu.hpp"
|
#include "frontend/menu.hpp"
|
||||||
#include "frontend/screens/Screen.hpp"
|
#include "frontend/screens/Screen.hpp"
|
||||||
#include "graphics/render/ModelsGenerator.hpp"
|
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "graphics/ui/GUI.hpp"
|
|
||||||
#include "graphics/ui/elements/Menu.hpp"
|
#include "graphics/ui/elements/Menu.hpp"
|
||||||
#include "logic/EngineController.hpp"
|
#include "graphics/ui/GUI.hpp"
|
||||||
|
#include "io/io.hpp"
|
||||||
|
#include "io/settings_io.hpp"
|
||||||
#include "logic/CommandsInterpreter.hpp"
|
#include "logic/CommandsInterpreter.hpp"
|
||||||
#include "logic/scripting/scripting.hpp"
|
#include "logic/EngineController.hpp"
|
||||||
#include "logic/scripting/scripting_hud.hpp"
|
#include "logic/scripting/scripting_hud.hpp"
|
||||||
|
#include "logic/scripting/scripting.hpp"
|
||||||
|
#include "Mainloop.hpp"
|
||||||
#include "network/Network.hpp"
|
#include "network/Network.hpp"
|
||||||
|
#include "ServerMainloop.hpp"
|
||||||
#include "util/platform.hpp"
|
#include "util/platform.hpp"
|
||||||
|
#include "util/stringutil.hpp"
|
||||||
#include "window/input.hpp"
|
#include "window/input.hpp"
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "world/Level.hpp"
|
|
||||||
#include "Mainloop.hpp"
|
|
||||||
#include "ServerMainloop.hpp"
|
|
||||||
#include "WindowControl.hpp"
|
#include "WindowControl.hpp"
|
||||||
#include "EnginePaths.hpp"
|
#include "world/Level.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
static debug::Logger logger("engine");
|
static debug::Logger logger("engine");
|
||||||
|
|
||||||
|
|
@ -84,6 +82,7 @@ void Engine::onContentLoad() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::initializeClient() {
|
void Engine::initializeClient() {
|
||||||
|
assets = std::make_unique<AssetsManagement>(*this);
|
||||||
windowControl = std::make_unique<WindowControl>(*this);
|
windowControl = std::make_unique<WindowControl>(*this);
|
||||||
auto [window, input] = windowControl->initialize();
|
auto [window, input] = windowControl->initialize();
|
||||||
|
|
||||||
|
|
@ -264,6 +263,7 @@ void Engine::applicationTick() {
|
||||||
|
|
||||||
void Engine::updateFrontend() {
|
void Engine::updateFrontend() {
|
||||||
double delta = time.getDelta();
|
double delta = time.getDelta();
|
||||||
|
assets->update();
|
||||||
updateHotkeys();
|
updateHotkeys();
|
||||||
audio::update(delta);
|
audio::update(delta);
|
||||||
gui->act(delta, window->getSize());
|
gui->act(delta, window->getSize());
|
||||||
|
|
@ -305,7 +305,7 @@ void Engine::renderFrame() {
|
||||||
screen->draw(time.getDelta());
|
screen->draw(time.getDelta());
|
||||||
|
|
||||||
DrawContext ctx(nullptr, *window, nullptr);
|
DrawContext ctx(nullptr, *window, nullptr);
|
||||||
gui->draw(ctx, *assets);
|
gui->draw(ctx, *assets->getStorage());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::saveSettings() {
|
void Engine::saveSettings() {
|
||||||
|
|
@ -363,33 +363,7 @@ void Engine::setLevelConsumer(OnWorldOpen levelConsumer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadAssets() {
|
void Engine::loadAssets() {
|
||||||
logger.info() << "loading assets";
|
assets->loadAssets(content->get());
|
||||||
Shader::preprocessor->setPaths(&paths->resPaths);
|
|
||||||
|
|
||||||
auto content = this->content->get();
|
|
||||||
|
|
||||||
auto new_assets = std::make_unique<Assets>();
|
|
||||||
AssetsLoader loader(*this, *new_assets, paths->resPaths);
|
|
||||||
AssetsLoader::addDefaults(loader, content);
|
|
||||||
|
|
||||||
// no need
|
|
||||||
// correct log messages order is more useful
|
|
||||||
// todo: before setting to true, check if GLSLExtension thread safe
|
|
||||||
bool threading = false; // look at three upper lines
|
|
||||||
if (threading) {
|
|
||||||
auto task = loader.startTask([=](){});
|
|
||||||
task->waitForEnd();
|
|
||||||
} else {
|
|
||||||
while (loader.hasNext()) {
|
|
||||||
loader.loadNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assets = std::move(new_assets);
|
|
||||||
if (content) {
|
|
||||||
ModelsGenerator::prepare(*content, *assets);
|
|
||||||
}
|
|
||||||
assets->setup();
|
|
||||||
gui->onAssetsLoad(assets.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadProject() {
|
void Engine::loadProject() {
|
||||||
|
|
@ -442,7 +416,11 @@ EngineSettings& Engine::getSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Assets* Engine::getAssets() {
|
Assets* Engine::getAssets() {
|
||||||
return assets.get();
|
return assets->getStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetsLoader& Engine::acquireBackgroundLoader() {
|
||||||
|
return assets->acquireBackgroundLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
EnginePaths& Engine::getPaths() {
|
EnginePaths& Engine::getPaths() {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Assets;
|
class Assets;
|
||||||
|
class AssetsLoader;
|
||||||
|
class AssetsManagement;
|
||||||
class ContentControl;
|
class ContentControl;
|
||||||
class EngineController;
|
class EngineController;
|
||||||
class EnginePaths;
|
class EnginePaths;
|
||||||
|
|
@ -52,7 +54,7 @@ class Engine : public util::ObjectsKeeper {
|
||||||
std::unique_ptr<EnginePaths> paths;
|
std::unique_ptr<EnginePaths> paths;
|
||||||
std::unique_ptr<Project> project;
|
std::unique_ptr<Project> project;
|
||||||
std::unique_ptr<SettingsHandler> settingsHandler;
|
std::unique_ptr<SettingsHandler> settingsHandler;
|
||||||
std::unique_ptr<Assets> assets;
|
std::unique_ptr<AssetsManagement> assets;
|
||||||
std::shared_ptr<Screen> screen;
|
std::shared_ptr<Screen> screen;
|
||||||
std::unique_ptr<ContentControl> content;
|
std::unique_ptr<ContentControl> content;
|
||||||
std::unique_ptr<EngineController> controller;
|
std::unique_ptr<EngineController> controller;
|
||||||
|
|
@ -109,6 +111,8 @@ public:
|
||||||
/// @brief Get active assets storage instance
|
/// @brief Get active assets storage instance
|
||||||
Assets* getAssets();
|
Assets* getAssets();
|
||||||
|
|
||||||
|
AssetsLoader& acquireBackgroundLoader();
|
||||||
|
|
||||||
/// @brief Get writeable engine settings structure instance
|
/// @brief Get writeable engine settings structure instance
|
||||||
EngineSettings& getSettings();
|
EngineSettings& getSettings();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,9 @@ ResPaths::ResPaths(std::vector<PathsRoot> roots)
|
||||||
}
|
}
|
||||||
|
|
||||||
io::path ResPaths::find(const std::string& filename) const {
|
io::path ResPaths::find(const std::string& filename) const {
|
||||||
|
if (filename.find(':') != std::string::npos) {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
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 / filename;
|
auto file = root.path / filename;
|
||||||
|
|
|
||||||
|
|
@ -741,7 +741,7 @@ void BlocksRenderer::build(
|
||||||
size_t endIndex = indexCount;
|
size_t endIndex = indexCount;
|
||||||
|
|
||||||
denseRender = true;
|
denseRender = true;
|
||||||
densePass = true;
|
densePass = settings.graphics.denseRender.get();
|
||||||
render(voxels, beginEnds);
|
render(voxels, beginEnds);
|
||||||
|
|
||||||
denseIndexCount = indexCount;
|
denseIndexCount = indexCount;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
|
#include "assets/assets_util.hpp"
|
||||||
#include "graphics/core/Atlas.hpp"
|
#include "graphics/core/Atlas.hpp"
|
||||||
#include "graphics/core/Batch2D.hpp"
|
#include "graphics/core/Batch2D.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
|
|
@ -16,37 +17,25 @@ Image::Image(GUI& gui, std::string texture, glm::vec2 size)
|
||||||
setInteractive(false);
|
setInteractive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util::TextureRegion Image::refreshTexture(const Assets& assets) {
|
||||||
|
auto region = util::get_texture_region(assets, texture, fallback);
|
||||||
|
if (region.texture && autoresize) {
|
||||||
|
setSize(glm::vec2(
|
||||||
|
region.texture->getWidth() * region.region.getWidth(),
|
||||||
|
region.texture->getHeight() * region.region.getHeight()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
void Image::draw(const DrawContext& pctx, const Assets& assets) {
|
void Image::draw(const DrawContext& pctx, const Assets& assets) {
|
||||||
glm::vec2 pos = calcPos();
|
glm::vec2 pos = calcPos();
|
||||||
auto batch = pctx.getBatch2D();
|
auto batch = pctx.getBatch2D();
|
||||||
|
|
||||||
Texture* texture = nullptr;
|
auto textureRegion = refreshTexture(assets);
|
||||||
auto separator = this->texture.find(':');
|
|
||||||
if (separator == std::string::npos) {
|
batch->setRegion(textureRegion.region);
|
||||||
texture = assets.get<Texture>(this->texture);
|
batch->texture(textureRegion.texture);
|
||||||
batch->texture(texture);
|
|
||||||
if (texture && autoresize) {
|
|
||||||
setSize(glm::vec2(texture->getWidth(), texture->getHeight()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto atlasName = this->texture.substr(0, separator);
|
|
||||||
if (auto atlas = assets.get<Atlas>(atlasName)) {
|
|
||||||
if (auto region =
|
|
||||||
atlas->getIf(this->texture.substr(separator + 1))) {
|
|
||||||
texture = atlas->getTexture();
|
|
||||||
batch->texture(atlas->getTexture());
|
|
||||||
batch->setRegion(*region);
|
|
||||||
if (autoresize) {
|
|
||||||
setSize(glm::vec2(
|
|
||||||
texture->getWidth() * region->getWidth(),
|
|
||||||
texture->getHeight() * region->getHeight()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
batch->texture(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
batch->rect(
|
batch->rect(
|
||||||
pos.x,
|
pos.x,
|
||||||
pos.y,
|
pos.y,
|
||||||
|
|
@ -73,10 +62,18 @@ const std::string& Image::getTexture() const {
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& Image::getFallback() const {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
void Image::setTexture(const std::string& name) {
|
void Image::setTexture(const std::string& name) {
|
||||||
texture = name;
|
texture = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Image::setFallback(const std::string& name) {
|
||||||
|
fallback = name;
|
||||||
|
}
|
||||||
|
|
||||||
void Image::setRegion(const UVRegion& region) {
|
void Image::setRegion(const UVRegion& region) {
|
||||||
this->region = region;
|
this->region = region;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,30 @@
|
||||||
#include "UINode.hpp"
|
#include "UINode.hpp"
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
struct TextureRegion;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class Image : public UINode {
|
class Image final : public UINode {
|
||||||
protected:
|
protected:
|
||||||
std::string texture;
|
std::string texture;
|
||||||
|
std::string fallback;
|
||||||
UVRegion region {};
|
UVRegion region {};
|
||||||
bool autoresize = false;
|
bool autoresize = false;
|
||||||
|
|
||||||
|
util::TextureRegion refreshTexture(const Assets& assets);
|
||||||
public:
|
public:
|
||||||
Image(GUI& gui, std::string texture, glm::vec2 size=glm::vec2(32,32));
|
Image(GUI& gui, std::string texture, glm::vec2 size=glm::vec2(32,32));
|
||||||
|
|
||||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||||
|
|
||||||
virtual void setAutoResize(bool flag);
|
void setAutoResize(bool flag);
|
||||||
virtual bool isAutoResize() const;
|
bool isAutoResize() const;
|
||||||
virtual const std::string& getTexture() const;
|
const std::string& getTexture() const;
|
||||||
virtual void setTexture(const std::string& name);
|
const std::string& getFallback() const;
|
||||||
|
void setTexture(const std::string& name);
|
||||||
|
void setFallback(const std::string& name);
|
||||||
void setRegion(const UVRegion& region);
|
void setRegion(const UVRegion& region);
|
||||||
const UVRegion& getRegion() const;
|
const UVRegion& getRegion() const;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -632,8 +632,10 @@ static std::shared_ptr<UINode> read_image(
|
||||||
const UiXmlReader& reader, const xml::xmlelement& element
|
const UiXmlReader& reader, const xml::xmlelement& element
|
||||||
) {
|
) {
|
||||||
std::string src = element.attr("src", "").getText();
|
std::string src = element.attr("src", "").getText();
|
||||||
auto image = std::make_shared<Image>(reader.getGUI(), src);
|
std::string fallback = element.attr("fallback", "").getText();
|
||||||
|
auto image = std::make_shared<Image>(reader.getGUI(), std::move(src));
|
||||||
read_uinode(reader, element, *image);
|
read_uinode(reader, element, *image);
|
||||||
|
image->setFallback(std::move(fallback));
|
||||||
|
|
||||||
if (element.has("region")) {
|
if (element.has("region")) {
|
||||||
auto vec = element.attr("region").asVec4();
|
auto vec = element.attr("region").asVec4();
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,9 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) {
|
||||||
builder.add("do-write-lights", &settings.debug.doWriteLights);
|
builder.add("do-write-lights", &settings.debug.doWriteLights);
|
||||||
builder.add("do-trace-shaders", &settings.debug.doTraceShaders);
|
builder.add("do-trace-shaders", &settings.debug.doTraceShaders);
|
||||||
builder.add("enable-experimental", &settings.debug.enableExperimental);
|
builder.add("enable-experimental", &settings.debug.enableExperimental);
|
||||||
|
|
||||||
|
builder.addSection("system");
|
||||||
|
builder.add("max-bg-asset-loaders", &settings.system.maxBgAssetLoaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
dv::value SettingsHandler::getValue(const std::string& name) const {
|
dv::value SettingsHandler::getValue(const std::string& name) const {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ struct ItemFuncsSet {
|
||||||
bool on_block_break_by : 1;
|
bool on_block_break_by : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ItemFuncNamesCache {
|
||||||
|
};
|
||||||
|
|
||||||
enum class ItemIconType {
|
enum class ItemIconType {
|
||||||
NONE, // invisible (core:empty) must not be rendered
|
NONE, // invisible (core:empty) must not be rendered
|
||||||
SPRITE, // textured quad: icon is `atlas_name:texture_name`
|
SPRITE, // textured quad: icon is `atlas_name:texture_name`
|
||||||
|
|
@ -75,6 +78,8 @@ struct ItemDef {
|
||||||
bool emissive = false;
|
bool emissive = false;
|
||||||
|
|
||||||
std::set<int> tags;
|
std::set<int> tags;
|
||||||
|
|
||||||
|
ItemFuncNamesCache eventNames;
|
||||||
} rt {};
|
} rt {};
|
||||||
|
|
||||||
ItemDef(const std::string& name);
|
ItemDef(const std::string& name);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
#include <iostream>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "LightSolver.hpp"
|
#include "LightSolver.hpp"
|
||||||
#include "Lightmap.hpp"
|
#include "Lightmap.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
|
|
@ -9,6 +6,8 @@
|
||||||
#include "voxels/voxel.hpp"
|
#include "voxels/voxel.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
LightSolver::LightSolver(const ContentIndices& contentIds, Chunks& chunks, int channel)
|
LightSolver::LightSolver(const ContentIndices& contentIds, Chunks& chunks, int channel)
|
||||||
: blockDefs(contentIds.blocks.getDefs()),
|
: blockDefs(contentIds.blocks.getDefs()),
|
||||||
chunks(chunks),
|
chunks(chunks),
|
||||||
|
|
@ -55,7 +54,7 @@ void LightSolver::remove(int x, int y, int z) {
|
||||||
lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0);
|
lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightSolver::solve(){
|
void LightSolver::solve(Chunk* prevailingChunk) {
|
||||||
const int coords[] = {
|
const int coords[] = {
|
||||||
0, 0, 1,
|
0, 0, 1,
|
||||||
0, 0,-1,
|
0, 0,-1,
|
||||||
|
|
@ -66,47 +65,54 @@ void LightSolver::solve(){
|
||||||
};
|
};
|
||||||
|
|
||||||
while (!remqueue.empty()){
|
while (!remqueue.empty()){
|
||||||
const lightentry entry = remqueue.front();
|
lightentry entry = std::move(remqueue.front());
|
||||||
remqueue.pop();
|
remqueue.pop();
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
int imul3 = i*3;
|
int imul3 = i * 3;
|
||||||
int x = entry.x+coords[imul3];
|
int x = entry.x+coords[imul3];
|
||||||
int y = entry.y+coords[imul3+1];
|
int y = entry.y+coords[imul3+1];
|
||||||
int z = entry.z+coords[imul3+2];
|
int z = entry.z+coords[imul3+2];
|
||||||
|
|
||||||
Chunk* chunk = chunks.getChunkByVoxel(x,y,z);
|
Chunk* chunk = prevailingChunk;
|
||||||
if (chunk) {
|
if (chunk == nullptr || !chunk->isBlockInside(x, z)) {
|
||||||
int lx = x - chunk->x * CHUNK_W;
|
chunk = chunks.getChunkByVoxel(x,y,z);
|
||||||
int lz = z - chunk->z * CHUNK_D;
|
if (chunk == nullptr) {
|
||||||
chunk->flags.modified = true;
|
continue;
|
||||||
|
}
|
||||||
|
} else if (y < 0 || y >= CHUNK_H) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
assert(chunk->lightmap != nullptr);
|
int lx = x - chunk->x * CHUNK_W;
|
||||||
auto& lightmap = *chunk->lightmap;
|
int lz = z - chunk->z * CHUNK_D;
|
||||||
|
chunk->flags.modified = true;
|
||||||
|
|
||||||
ubyte light = lightmap.get(lx,y,lz, channel);
|
assert(chunk->lightmap != nullptr);
|
||||||
if (light != 0 && light == entry.light-1){
|
auto& lightmap = *chunk->lightmap;
|
||||||
voxel* vox = chunks.get(x, y, z);
|
|
||||||
if (vox && vox->id != 0) {
|
ubyte light = lightmap.get(lx,y,lz, channel);
|
||||||
const Block* block = blockDefs[vox->id];
|
if (light != 0 && light == entry.light-1) {
|
||||||
if (uint8_t emission = block->emission[channel]) {
|
voxel* vox = chunks.get(x, y, z);
|
||||||
addqueue.push(lightentry {x, y, z, emission});
|
if (vox && vox->id != 0) {
|
||||||
lightmap.set(lx, y, lz, channel, emission);
|
const Block* block = blockDefs[vox->id];
|
||||||
}
|
if (uint8_t emission = block->emission[channel]) {
|
||||||
else lightmap.set(lx, y, lz, channel, 0);
|
addqueue.push(lightentry {x, y, z, emission});
|
||||||
|
lightmap.set(lx, y, lz, channel, emission);
|
||||||
}
|
}
|
||||||
else lightmap.set(lx, y, lz, channel, 0);
|
else lightmap.set(lx, y, lz, channel, 0);
|
||||||
remqueue.push(lightentry {x, y, z, light});
|
|
||||||
}
|
|
||||||
else if (light >= entry.light){
|
|
||||||
addqueue.push(lightentry {x, y, z, light});
|
|
||||||
}
|
}
|
||||||
|
else lightmap.set(lx, y, lz, channel, 0);
|
||||||
|
remqueue.push(lightentry {x, y, z, light});
|
||||||
|
}
|
||||||
|
else if (light >= entry.light) {
|
||||||
|
addqueue.push(lightentry {x, y, z, light});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!addqueue.empty()){
|
while (!addqueue.empty()){
|
||||||
const lightentry entry = addqueue.front();
|
lightentry entry = std::move(addqueue.front());
|
||||||
addqueue.pop();
|
addqueue.pop();
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
|
|
@ -115,10 +121,16 @@ void LightSolver::solve(){
|
||||||
int y = entry.y+coords[imul3+1];
|
int y = entry.y+coords[imul3+1];
|
||||||
int z = entry.z+coords[imul3+2];
|
int z = entry.z+coords[imul3+2];
|
||||||
|
|
||||||
Chunk* chunk = chunks.getChunkByVoxel(x,y,z);
|
Chunk* chunk = prevailingChunk;
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr || !chunk->isBlockInside(x, z)) {
|
||||||
|
chunk = chunks.getChunkByVoxel(x,y,z);
|
||||||
|
if (chunk == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (y < 0 || y >= CHUNK_H) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(chunk->lightmap != nullptr);
|
assert(chunk->lightmap != nullptr);
|
||||||
auto& lightmap = *chunk->lightmap;
|
auto& lightmap = *chunk->lightmap;
|
||||||
int lx = x - chunk->x * CHUNK_W;
|
int lx = x - chunk->x * CHUNK_W;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <queue>
|
#include "util/array_queue.hpp"
|
||||||
|
|
||||||
|
class Chunk;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
class ContentIndices;
|
class ContentIndices;
|
||||||
class Block;
|
class Block;
|
||||||
|
|
@ -14,8 +15,8 @@ struct lightentry {
|
||||||
};
|
};
|
||||||
|
|
||||||
class LightSolver {
|
class LightSolver {
|
||||||
std::queue<lightentry> addqueue;
|
util::array_queue<lightentry> addqueue;
|
||||||
std::queue<lightentry> remqueue;
|
util::array_queue<lightentry> remqueue;
|
||||||
const Block* const* blockDefs;
|
const Block* const* blockDefs;
|
||||||
Chunks& chunks;
|
Chunks& chunks;
|
||||||
int channel;
|
int channel;
|
||||||
|
|
@ -25,5 +26,5 @@ public:
|
||||||
void add(int x, int y, int z);
|
void add(int x, int y, int z);
|
||||||
void add(int x, int y, int z, int emission);
|
void add(int x, int y, int z, int emission);
|
||||||
void remove(int x, int y, int z);
|
void remove(int x, int y, int z);
|
||||||
void solve();
|
void solve(Chunk* prevailingChunk = nullptr);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -167,10 +167,10 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
solverR.solve();
|
solverR.solve(chunk);
|
||||||
solverG.solve();
|
solverG.solve(chunk);
|
||||||
solverB.solve();
|
solverB.solve(chunk);
|
||||||
solverS.solve();
|
solverS.solve(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lighting::onBlockSet(int x, int y, int z, blockid_t id){
|
void Lighting::onBlockSet(int x, int y, int z, blockid_t id){
|
||||||
|
|
@ -180,9 +180,10 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){
|
||||||
solverB->remove(x,y,z);
|
solverB->remove(x,y,z);
|
||||||
|
|
||||||
if (id == 0){
|
if (id == 0){
|
||||||
solverR->solve();
|
auto chunk = chunks.getChunkByVoxel(glm::ivec3{x, y, z});
|
||||||
solverG->solve();
|
solverR->solve(chunk);
|
||||||
solverB->solve();
|
solverG->solve(chunk);
|
||||||
|
solverB->solve(chunk);
|
||||||
if (chunks.getLight(x,y+1,z, 3) == 0xF){
|
if (chunks.getLight(x,y+1,z, 3) == 0xF){
|
||||||
for (int i = y; i >= 0; i--){
|
for (int i = y; i >= 0; i--){
|
||||||
voxel* vox = chunks.get(x,i,z);
|
voxel* vox = chunks.get(x,i,z);
|
||||||
|
|
@ -191,17 +192,30 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){
|
||||||
solverS->add(x,i,z, 0xF);
|
solverS->add(x,i,z, 0xF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
solverR->add(x,y+1,z); solverG->add(x,y+1,z); solverB->add(x,y+1,z); solverS->add(x,y+1,z);
|
const int coords[] = {
|
||||||
solverR->add(x,y-1,z); solverG->add(x,y-1,z); solverB->add(x,y-1,z); solverS->add(x,y-1,z);
|
0, 0, 1,
|
||||||
solverR->add(x+1,y,z); solverG->add(x+1,y,z); solverB->add(x+1,y,z); solverS->add(x+1,y,z);
|
0, 0,-1,
|
||||||
solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z);
|
0, 1, 0,
|
||||||
solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1);
|
0,-1, 0,
|
||||||
solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1);
|
1, 0, 0,
|
||||||
solverR->solve();
|
-1, 0, 0
|
||||||
solverG->solve();
|
};
|
||||||
solverB->solve();
|
for (int i = 0; i < 6; i++) {
|
||||||
solverS->solve();
|
int lx = x + coords[i * 3];
|
||||||
|
int ly = y + coords[i * 3 + 1];
|
||||||
|
int lz = z + coords[i * 3 + 2];
|
||||||
|
|
||||||
|
solverR->add(lx, ly, lz);
|
||||||
|
solverG->add(lx, ly, lz);
|
||||||
|
solverB->add(lx, ly, lz);
|
||||||
|
solverS->add(lx, ly, lz);
|
||||||
|
solverR->solve(chunk);
|
||||||
|
solverG->solve(chunk);
|
||||||
|
solverB->solve(chunk);
|
||||||
|
solverS->solve(chunk);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
auto chunk = chunks.getChunkByVoxel(glm::ivec3{x, y, z});
|
||||||
if (!block.skyLightPassing){
|
if (!block.skyLightPassing){
|
||||||
solverS->remove(x,y,z);
|
solverS->remove(x,y,z);
|
||||||
for (int i = y-1; i >= 0; i--){
|
for (int i = y-1; i >= 0; i--){
|
||||||
|
|
@ -210,19 +224,19 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
solverS->solve();
|
solverS->solve(chunk);
|
||||||
}
|
}
|
||||||
solverR->solve();
|
solverR->solve(chunk);
|
||||||
solverG->solve();
|
solverG->solve(chunk);
|
||||||
solverB->solve();
|
solverB->solve(chunk);
|
||||||
|
|
||||||
if (block.emission[0] || block.emission[1] || block.emission[2]){
|
if (block.emission[0] || block.emission[1] || block.emission[2]){
|
||||||
solverR->add(x,y,z,block.emission[0]);
|
solverR->add(x,y,z,block.emission[0]);
|
||||||
solverG->add(x,y,z,block.emission[1]);
|
solverG->add(x,y,z,block.emission[1]);
|
||||||
solverB->add(x,y,z,block.emission[2]);
|
solverB->add(x,y,z,block.emission[2]);
|
||||||
solverR->solve();
|
solverR->solve(chunk);
|
||||||
solverG->solve();
|
solverG->solve(chunk);
|
||||||
solverB->solve();
|
solverB->solve(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
#include "BlocksController.hpp"
|
#include "BlocksController.hpp"
|
||||||
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "items/Inventories.hpp"
|
#include "items/Inventories.hpp"
|
||||||
#include "items/Inventory.hpp"
|
#include "items/Inventory.hpp"
|
||||||
|
|
@ -175,12 +173,8 @@ void BlocksController::randomTick(
|
||||||
void BlocksController::randomTick(int tickid, int parts, uint padding) {
|
void BlocksController::randomTick(int tickid, int parts, uint padding) {
|
||||||
auto indices = level.content.getIndices();
|
auto indices = level.content.getIndices();
|
||||||
|
|
||||||
std::set<uint64_t> chunksIterated;
|
|
||||||
|
|
||||||
for (const auto& [pid, player] : *level.players) {
|
for (const auto& [pid, player] : *level.players) {
|
||||||
const auto& chunks = *player->chunks;
|
const auto& chunks = *player->chunks;
|
||||||
int offsetX = chunks.getOffsetX();
|
|
||||||
int offsetY = chunks.getOffsetY();
|
|
||||||
int width = chunks.getWidth();
|
int width = chunks.getWidth();
|
||||||
int height = chunks.getHeight();
|
int height = chunks.getHeight();
|
||||||
int segments = 4;
|
int segments = 4;
|
||||||
|
|
@ -195,20 +189,15 @@ void BlocksController::randomTick(int tickid, int parts, uint padding) {
|
||||||
if (chunk == nullptr || !chunk->flags.lighted) {
|
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
union {
|
if (chunk->lastRandomTickId == randomTickId) {
|
||||||
int32_t pos[2];
|
|
||||||
uint64_t key;
|
|
||||||
} posU;
|
|
||||||
posU.pos[0] = x + offsetX;
|
|
||||||
posU.pos[1] = z + offsetY;
|
|
||||||
if (chunksIterated.find(posU.key) != chunksIterated.end()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
chunksIterated.insert(posU.key);
|
chunk->lastRandomTickId = randomTickId;
|
||||||
randomTick(*chunk, segments, indices);
|
randomTick(*chunk, segments, indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
randomTickId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t BlocksController::createBlockInventory(int x, int y, int z) {
|
int64_t BlocksController::createBlockInventory(int x, int y, int z) {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ class BlocksController {
|
||||||
util::Clock worldTickClock;
|
util::Clock worldTickClock;
|
||||||
FastRandom random {};
|
FastRandom random {};
|
||||||
std::vector<on_block_interaction> blockInteractionCallbacks;
|
std::vector<on_block_interaction> blockInteractionCallbacks;
|
||||||
|
uint64_t randomTickId = 0;
|
||||||
public:
|
public:
|
||||||
BlocksController(const Level& level, Lighting* lighting);
|
BlocksController(const Level& level, Lighting* lighting);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -276,8 +276,8 @@ void EngineController::createWorld(
|
||||||
auto folder = paths.getWorldsFolder() / name;
|
auto folder = paths.getWorldsFolder() / name;
|
||||||
|
|
||||||
call(engine, [this, &paths, folder]() {
|
call(engine, [this, &paths, folder]() {
|
||||||
engine.getContentControl().loadContent();
|
|
||||||
paths.setCurrentWorldFolder(folder);
|
paths.setCurrentWorldFolder(folder);
|
||||||
|
engine.getContentControl().loadContent();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto& contentControl = engine.getContentControl();
|
auto& contentControl = engine.getContentControl();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "api_lua.hpp"
|
#include "api_lua.hpp"
|
||||||
|
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
|
#include "assets/AssetsLoader.hpp"
|
||||||
#include "coders/png.hpp"
|
#include "coders/png.hpp"
|
||||||
#include "coders/vcm.hpp"
|
#include "coders/vcm.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
|
|
@ -24,6 +25,14 @@ static void load_texture(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_request_texture(lua::State* L) {
|
||||||
|
std::string filename = lua::require_string(L, 1);
|
||||||
|
std::string alias = lua::require_string(L, 2);
|
||||||
|
auto& loader = engine->acquireBackgroundLoader();
|
||||||
|
loader.add(AssetType::TEXTURE, filename, alias);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int l_load_texture(lua::State* L) {
|
static int l_load_texture(lua::State* L) {
|
||||||
if (lua::isstring(L, 3) && lua::require_lstring(L, 3) != "png") {
|
if (lua::isstring(L, 3) && lua::require_lstring(L, 3) != "png") {
|
||||||
throw std::runtime_error("unsupportd image format");
|
throw std::runtime_error("unsupportd image format");
|
||||||
|
|
@ -108,6 +117,7 @@ static int l_to_canvas(lua::State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const luaL_Reg assetslib[] = {
|
const luaL_Reg assetslib[] = {
|
||||||
|
{"request_texture", lua::wrap<l_request_texture>},
|
||||||
{"load_texture", lua::wrap<l_load_texture>},
|
{"load_texture", lua::wrap<l_load_texture>},
|
||||||
{"parse_model", lua::wrap<l_parse_model>},
|
{"parse_model", lua::wrap<l_parse_model>},
|
||||||
{"to_canvas", lua::wrap<l_to_canvas>},
|
{"to_canvas", lua::wrap<l_to_canvas>},
|
||||||
|
|
|
||||||
|
|
@ -397,6 +397,13 @@ static int p_get_src(UINode* node, lua::State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int p_get_fallback(UINode* node, lua::State* L) {
|
||||||
|
if (auto image = dynamic_cast<Image*>(node)) {
|
||||||
|
return lua::pushstring(L, image->getFallback());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int p_get_region(UINode* node, lua::State* L) {
|
static int p_get_region(UINode* node, lua::State* L) {
|
||||||
if (auto image = dynamic_cast<Image*>(node)) {
|
if (auto image = dynamic_cast<Image*>(node)) {
|
||||||
const auto& region = image->getRegion();
|
const auto& region = image->getRegion();
|
||||||
|
|
@ -663,6 +670,7 @@ static int l_gui_getattr(lua::State* L) {
|
||||||
{"syntax", p_get_syntax},
|
{"syntax", p_get_syntax},
|
||||||
{"markup", p_get_markup},
|
{"markup", p_get_markup},
|
||||||
{"src", p_get_src},
|
{"src", p_get_src},
|
||||||
|
{"fallback", p_get_fallback},
|
||||||
{"value", p_get_value},
|
{"value", p_get_value},
|
||||||
{"min", p_get_min},
|
{"min", p_get_min},
|
||||||
{"max", p_get_max},
|
{"max", p_get_max},
|
||||||
|
|
@ -790,6 +798,11 @@ static void p_set_src(UINode* node, lua::State* L, int idx) {
|
||||||
modelviewer->setModel(lua::require_string(L, idx));
|
modelviewer->setModel(lua::require_string(L, idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static void p_set_fallback(UINode* node, lua::State* L, int idx) {
|
||||||
|
if (auto image = dynamic_cast<Image*>(node)) {
|
||||||
|
image->setFallback(lua::require_string(L, idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
static void p_set_region(UINode* node, lua::State* L, int idx) {
|
static void p_set_region(UINode* node, lua::State* L, int idx) {
|
||||||
if (auto image = dynamic_cast<Image*>(node)) {
|
if (auto image = dynamic_cast<Image*>(node)) {
|
||||||
auto vec = lua::tovec4(L, idx);
|
auto vec = lua::tovec4(L, idx);
|
||||||
|
|
@ -962,6 +975,7 @@ static int l_gui_setattr(lua::State* L) {
|
||||||
{"syntax", p_set_syntax},
|
{"syntax", p_set_syntax},
|
||||||
{"markup", p_set_markup},
|
{"markup", p_set_markup},
|
||||||
{"src", p_set_src},
|
{"src", p_set_src},
|
||||||
|
{"fallback", p_set_fallback},
|
||||||
{"caret", p_set_caret},
|
{"caret", p_set_caret},
|
||||||
{"value", p_set_value},
|
{"value", p_set_value},
|
||||||
{"min", p_set_min},
|
{"min", p_set_min},
|
||||||
|
|
|
||||||
|
|
@ -87,10 +87,10 @@ static int l_pack_get_info(
|
||||||
lua::setfield(L, "path");
|
lua::setfield(L, "path");
|
||||||
|
|
||||||
if (!engine->isHeadless()) {
|
if (!engine->isHeadless()) {
|
||||||
auto assets = engine->getAssets();
|
auto& assetsLoader = engine->acquireBackgroundLoader();
|
||||||
std::string icon = pack.id + ".icon";
|
std::string icon = pack.id + ".icon";
|
||||||
if (!AssetsLoader::loadExternalTexture(
|
if (!AssetsLoader::loadExternalTexture(
|
||||||
assets, icon, {pack.folder / "icon.png"}
|
assetsLoader, icon, {pack.folder / "icon.png"}
|
||||||
)) {
|
)) {
|
||||||
icon = "gui/no_icon";
|
icon = "gui/no_icon";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,9 @@ static int l_get_list(lua::State* L) {
|
||||||
lua::pushstring(L, name);
|
lua::pushstring(L, name);
|
||||||
lua::setfield(L, "name");
|
lua::setfield(L, "name");
|
||||||
|
|
||||||
auto assets = engine->getAssets();
|
|
||||||
std::string icon = "world#" + name + ".icon";
|
std::string icon = "world#" + name + ".icon";
|
||||||
if (!engine->isHeadless() && !AssetsLoader::loadExternalTexture(
|
if (!engine->isHeadless() && !AssetsLoader::loadExternalTexture(
|
||||||
assets,
|
engine->acquireBackgroundLoader(),
|
||||||
icon,
|
icon,
|
||||||
{worlds[i] / "icon.png",
|
{worlds[i] / "icon.png",
|
||||||
worlds[i] / "preview.png"}
|
worlds[i] / "preview.png"}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
#include "scripting.hpp"
|
#include "scripting.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "scripting_commons.hpp"
|
#include "scripting_commons.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "content/ContentPack.hpp"
|
#include "content/ContentPack.hpp"
|
||||||
|
|
@ -28,6 +25,9 @@
|
||||||
#include "world/World.hpp"
|
#include "world/World.hpp"
|
||||||
#include "interfaces/Process.hpp"
|
#include "interfaces/Process.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace scripting;
|
using namespace scripting;
|
||||||
|
|
||||||
static debug::Logger logger("scripting");
|
static debug::Logger logger("scripting");
|
||||||
|
|
@ -391,15 +391,15 @@ void scripting::on_blocks_tick(const Block& block, int tps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::update_block(const Block& block, const glm::ivec3& pos) {
|
void scripting::update_block(const Block& block, const glm::ivec3& pos) {
|
||||||
std::string name = block.name + ".update";
|
lua::emit_event(lua::get_main_state(), block.rt.eventNames.update,
|
||||||
lua::emit_event(lua::get_main_state(), name, [pos](auto L) {
|
[pos](auto L) {
|
||||||
return lua::pushivec_stack(L, pos);
|
return lua::pushivec_stack(L, pos);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::random_update_block(const Block& block, const glm::ivec3& pos) {
|
void scripting::random_update_block(const Block& block, const glm::ivec3& pos) {
|
||||||
std::string name = block.name + ".randupdate";
|
lua::emit_event(lua::get_main_state(), block.rt.eventNames.randomUpdate,
|
||||||
lua::emit_event(lua::get_main_state(), name, [pos](auto L) {
|
[pos](auto L) {
|
||||||
return lua::pushivec_stack(L, pos);
|
return lua::pushivec_stack(L, pos);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -660,7 +660,8 @@ void scripting::load_content_script(
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const io::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
BlockFuncsSet& funcsset
|
BlockFuncsSet& funcsset,
|
||||||
|
BlockFuncNamesCache& namesCache
|
||||||
) {
|
) {
|
||||||
int env = *senv;
|
int env = *senv;
|
||||||
lua::pop(lua::get_main_state(), load_script(env, "block", file, fileName));
|
lua::pop(lua::get_main_state(), load_script(env, "block", file, fileName));
|
||||||
|
|
@ -686,6 +687,9 @@ void scripting::load_content_script(
|
||||||
register_event(env, "on_block_present", prefix + ".blockpresent");
|
register_event(env, "on_block_present", prefix + ".blockpresent");
|
||||||
funcsset.onblockremoved =
|
funcsset.onblockremoved =
|
||||||
register_event(env, "on_block_removed", prefix + ".blockremoved");
|
register_event(env, "on_block_removed", prefix + ".blockremoved");
|
||||||
|
|
||||||
|
namesCache.randomUpdate = prefix + ".update";
|
||||||
|
namesCache.randomUpdate = prefix + ".randupdate";
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::load_content_script(
|
void scripting::load_content_script(
|
||||||
|
|
@ -693,7 +697,8 @@ void scripting::load_content_script(
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const io::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
ItemFuncsSet& funcsset
|
ItemFuncsSet& funcsset,
|
||||||
|
ItemFuncNamesCache& namesCache
|
||||||
) {
|
) {
|
||||||
int env = *senv;
|
int env = *senv;
|
||||||
lua::pop(lua::get_main_state(), load_script(env, "item", file, fileName));
|
lua::pop(lua::get_main_state(), load_script(env, "item", file, fileName));
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ struct ItemDef;
|
||||||
class Inventory;
|
class Inventory;
|
||||||
class UiDocument;
|
class UiDocument;
|
||||||
struct BlockFuncsSet;
|
struct BlockFuncsSet;
|
||||||
|
struct BlockFuncNamesCache;
|
||||||
struct ItemFuncsSet;
|
struct ItemFuncsSet;
|
||||||
|
struct ItemFuncNamesCache;
|
||||||
struct WorldFuncsSet;
|
struct WorldFuncsSet;
|
||||||
struct UserComponent;
|
struct UserComponent;
|
||||||
struct uidocscript;
|
struct uidocscript;
|
||||||
|
|
@ -168,7 +170,8 @@ namespace scripting {
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const io::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
BlockFuncsSet& funcsset
|
BlockFuncsSet& funcsset,
|
||||||
|
BlockFuncNamesCache& namesCache
|
||||||
);
|
);
|
||||||
|
|
||||||
/// @brief Load script associated with an Item
|
/// @brief Load script associated with an Item
|
||||||
|
|
@ -182,7 +185,8 @@ namespace scripting {
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
const io::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName,
|
const std::string& fileName,
|
||||||
ItemFuncsSet& funcsset
|
ItemFuncsSet& funcsset,
|
||||||
|
ItemFuncNamesCache& namesCache
|
||||||
);
|
);
|
||||||
|
|
||||||
/// @brief Load component script
|
/// @brief Load component script
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,10 @@ struct UiSettings {
|
||||||
struct NetworkSettings {
|
struct NetworkSettings {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SystemSettings {
|
||||||
|
IntegerSetting maxBgAssetLoaders {3, -4, 16};
|
||||||
|
};
|
||||||
|
|
||||||
struct EngineSettings {
|
struct EngineSettings {
|
||||||
AudioSettings audio;
|
AudioSettings audio;
|
||||||
DisplaySettings display;
|
DisplaySettings display;
|
||||||
|
|
@ -125,4 +129,5 @@ struct EngineSettings {
|
||||||
UiSettings ui;
|
UiSettings ui;
|
||||||
NetworkSettings network;
|
NetworkSettings network;
|
||||||
PathfindingSettings pathfinding;
|
PathfindingSettings pathfinding;
|
||||||
|
SystemSettings system;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <optional>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -48,6 +49,7 @@ namespace util {
|
||||||
std::atomic<int> busyWorkers = 0;
|
std::atomic<int> busyWorkers = 0;
|
||||||
std::atomic<uint> jobsDone = 0;
|
std::atomic<uint> jobsDone = 0;
|
||||||
std::atomic<bool> working = true;
|
std::atomic<bool> working = true;
|
||||||
|
supplier<std::optional<T>> jobsSource = nullptr;
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
bool standaloneResults = true;
|
bool standaloneResults = true;
|
||||||
bool stopOnFail = true;
|
bool stopOnFail = true;
|
||||||
|
|
@ -151,6 +153,10 @@ namespace util {
|
||||||
return working;
|
return working;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setJobsSource(supplier<std::optional<T>>&& source) {
|
||||||
|
jobsSource = std::move(source);
|
||||||
|
}
|
||||||
|
|
||||||
void terminate() override {
|
void terminate() override {
|
||||||
if (!working) {
|
if (!working) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -227,6 +233,22 @@ namespace util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (jobsSource) {
|
||||||
|
bool jobsAdded = false;
|
||||||
|
std::lock_guard<std::mutex> jobsLock(jobsMutex);
|
||||||
|
while (true) {
|
||||||
|
auto job = jobsSource();
|
||||||
|
if (job.has_value()) {
|
||||||
|
jobs.push(std::move(job.value()));
|
||||||
|
jobsAdded = true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (jobsAdded) {
|
||||||
|
jobsMutexCondition.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (failed) {
|
if (failed) {
|
||||||
throw std::runtime_error("some job failed");
|
throw std::runtime_error("some job failed");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
76
src/util/array_queue.hpp
Normal file
76
src/util/array_queue.hpp
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
template <typename T>
|
||||||
|
class array_queue {
|
||||||
|
public:
|
||||||
|
array_queue(size_t initCapacity = 8)
|
||||||
|
: _capacity(initCapacity),
|
||||||
|
_size(0),
|
||||||
|
_front(0),
|
||||||
|
_back(0),
|
||||||
|
_data(std::make_unique<T[]>(_capacity)) {
|
||||||
|
if (initCapacity == 0 || (initCapacity & (initCapacity - 1)) != 0) {
|
||||||
|
throw std::invalid_argument("initCapacity must be positive power of 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~array_queue() {
|
||||||
|
while (!empty()) {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(T&& value) {
|
||||||
|
if (_back == _front && _size) {
|
||||||
|
grow();
|
||||||
|
}
|
||||||
|
_data[_back] = std::forward<T>(value);
|
||||||
|
_back = (_back + 1) & (_capacity - 1);
|
||||||
|
++_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& front() {
|
||||||
|
return _data[_front];
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop() {
|
||||||
|
_data[_front].~T();
|
||||||
|
_front = (_front + 1) & (_capacity - 1);
|
||||||
|
--_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return _size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t _capacity;
|
||||||
|
size_t _size;
|
||||||
|
size_t _front;
|
||||||
|
size_t _back;
|
||||||
|
std::unique_ptr<T[]> _data;
|
||||||
|
|
||||||
|
void grow() {
|
||||||
|
size_t newCapacity = _capacity * 2;
|
||||||
|
auto newData = std::make_unique<T[]>(newCapacity);
|
||||||
|
|
||||||
|
std::move(_data.get() + _front, _data.get() + _capacity, newData.get());
|
||||||
|
std::move(_data.get(), _data.get() + _front, newData.get() + (_capacity - _front));
|
||||||
|
|
||||||
|
_back = _size;
|
||||||
|
_front = 0;
|
||||||
|
|
||||||
|
_data.reset(newData.release());
|
||||||
|
_capacity = newCapacity;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -54,6 +54,11 @@ struct BlockFuncsSet {
|
||||||
bool onblockremoved : 1;
|
bool onblockremoved : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BlockFuncNamesCache {
|
||||||
|
std::string update;
|
||||||
|
std::string randomUpdate;
|
||||||
|
};
|
||||||
|
|
||||||
struct CoordSystem {
|
struct CoordSystem {
|
||||||
std::array<glm::ivec3, 3> axes;
|
std::array<glm::ivec3, 3> axes;
|
||||||
/// @brief Grid 3d position fix offset (for negative vectors)
|
/// @brief Grid 3d position fix offset (for negative vectors)
|
||||||
|
|
@ -296,6 +301,8 @@ public:
|
||||||
blockid_t surfaceReplacement = 0;
|
blockid_t surfaceReplacement = 0;
|
||||||
|
|
||||||
std::set<int> tags;
|
std::set<int> tags;
|
||||||
|
|
||||||
|
BlockFuncNamesCache eventNames;
|
||||||
} rt {};
|
} rt {};
|
||||||
|
|
||||||
Block(const std::string& name);
|
Block(const std::string& name);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ public:
|
||||||
bool dirtyHeights : 1;
|
bool dirtyHeights : 1;
|
||||||
} flags {};
|
} flags {};
|
||||||
|
|
||||||
|
uint64_t lastRandomTickId = -1;
|
||||||
|
|
||||||
/// @brief Block inventories map where key is index of block in voxels array
|
/// @brief Block inventories map where key is index of block in voxels array
|
||||||
ChunkInventoriesMap inventories;
|
ChunkInventoriesMap inventories;
|
||||||
/// @brief Blocks metadata heap
|
/// @brief Blocks metadata heap
|
||||||
|
|
@ -81,4 +83,10 @@ public:
|
||||||
glm::vec3((x + 1) * CHUNK_W, INFINITY, (z + 1) * CHUNK_D)
|
glm::vec3((x + 1) * CHUNK_W, INFINITY, (z + 1) * CHUNK_D)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isBlockInside(int x, int z) const {
|
||||||
|
x -= this->x * CHUNK_W;
|
||||||
|
z -= this->z * CHUNK_D;
|
||||||
|
return x >= 0 && z >= 0 && x < CHUNK_W && z < CHUNK_D;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue