Merge branch 'main' into release-0.26

This commit is contained in:
MihailRis 2025-01-22 00:36:49 +03:00
commit b37c71059a
28 changed files with 111 additions and 59 deletions

View File

@ -32,7 +32,7 @@ jobs:
# install EnTT # install EnTT
git clone https://github.com/skypjack/entt.git git clone https://github.com/skypjack/entt.git
cd entt/build cd entt/build
cmake -DCMAKE_BUILD_TYPE=Release .. cmake -DCMAKE_BUILD_TYPE=Release -DENTT_INSTALL=on ..
sudo make install sudo make install
cd ../.. cd ../..
- name: Configure - name: Configure

View File

@ -46,7 +46,7 @@ jobs:
# install EnTT # install EnTT
git clone https://github.com/skypjack/entt.git git clone https://github.com/skypjack/entt.git
cd entt/build cd entt/build
cmake -DCMAKE_BUILD_TYPE=Release .. cmake -DCMAKE_BUILD_TYPE=Release -DENTT_INSTALL=on ..
sudo make install sudo make install
cd ../.. cd ../..

View File

@ -14,7 +14,7 @@
```sh ```sh
git clone https://github.com/skypjack/entt.git git clone https://github.com/skypjack/entt.git
cd entt/build cd entt/build
cmake -DCMAKE_BUILD_TYPE=Release .. cmake -DCMAKE_BUILD_TYPE=Release -DENTT_INSTALL=on ..
sudo make install sudo make install
``` ```

View File

@ -18,7 +18,7 @@ Creates a rule. If a handler is specified, returns the id for deletion.
> Rules that have not been created can be used, but resetting via rules.reset will result in setting the value to nil. > Rules that have not been created can be used, but resetting via rules.reset will result in setting the value to nil.
```lua ```lua
rules.listen( rules.listen(
-- rule name -- rule name
name: str, name: str,
-- value change handler function -- value change handler function

View File

@ -26,6 +26,9 @@ entity:get_uid() -> int
entity:get_component(name: str) -> component or nil entity:get_component(name: str) -> component or nil
-- Checks for the presence of a component by name -- Checks for the presence of a component by name
entity:has_component(name: str) -> bool entity:has_component(name: str) -> bool
-- Enables/disables the component
entity:set_enabled(name: str, enable: bool)
``` ```
## Built-in components ## Built-in components

View File

@ -26,6 +26,9 @@ entity:get_uid() -> int
entity:get_component(name: str) -> компонент или nil entity:get_component(name: str) -> компонент или nil
-- Проверяет наличие компонента по имени -- Проверяет наличие компонента по имени
entity:has_component(name: str) -> bool entity:has_component(name: str) -> bool
-- Включает/выключает компонент по имени
entity:set_enabled(name: str, enable: bool)
``` ```
## Встроенные компоненты ## Встроенные компоненты

View File

@ -2,5 +2,6 @@
"texture": "lamp", "texture": "lamp",
"emission": [15, 14, 13], "emission": [15, 14, 13],
"shadeless": true, "shadeless": true,
"material": "base:glass",
"base:durability": 0.3 "base:durability": 0.3
} }

View File

@ -12,7 +12,7 @@
</container> </container>
<container id="logContainer" pos="0,60" <container id="logContainer" pos="0,60"
size-func="unpack(vec2.add(gui.get_viewport(), {0,-100}))"> size-func="unpack(vec2.add(gui.get_viewport(), {-350,-100}))">
<textbox <textbox
id='log' id='log'
color='0' color='0'
@ -20,7 +20,7 @@
margin='0' margin='0'
editable='false' editable='false'
multiline='true' multiline='true'
size-func="gui.get_viewport()[1],40" size-func="gui.get_viewport()[1]-350,40"
gravity="bottom-left" gravity="bottom-left"
markup="md" markup="md"
></textbox> ></textbox>

View File

@ -7,18 +7,11 @@ local initialized = false
local max_lines = 15 local max_lines = 15
local animation_fps = 30 local animation_fps = 30
local function remove_line(line)
document[line[1]]:destruct()
time.post_runnable(function()
if world.is_open() then document.root:reposition() end
end)
end
local function update_line(line, uptime) local function update_line(line, uptime)
local diff = uptime - line[2] local diff = uptime - line[2]
if diff > timeout then if diff > timeout then
remove_line(line) document[line[1]]:destruct()
table.insert(dead_lines, i) table.insert(dead_lines, table.index(lines, line))
elseif diff > timeout-fadeout then elseif diff > timeout-fadeout then
local opacity = (timeout - diff) / fadeout local opacity = (timeout - diff) / fadeout
document[line[1]].color = {0, 0, 0, opacity * 80} document[line[1]].color = {0, 0, 0, opacity * 80}
@ -27,16 +20,16 @@ local function update_line(line, uptime)
end end
events.on("core:chat", function(message) events.on("core:chat", function(message)
while #lines >= max_lines do
document[lines[1][1]]:destruct()
table.remove(lines, 1)
end
local current_time = time.uptime() local current_time = time.uptime()
local id = 'l'..tostring(nextid) local id = 'l'..tostring(nextid)
document.root:add(gui.template("chat_line", {id=id})) document.root:add(gui.template("chat_line", {id=id}))
document.root:reposition() document.root:reposition()
document[id.."L"].text = message document[id.."L"].text = message
nextid = nextid + 1 nextid = nextid + 1
if #lines == max_lines then
remove_line(lines[1])
table.remove(lines, 1)
end
table.insert(lines, {id, current_time}) table.insert(lines, {id, current_time})
end) end)

View File

@ -313,8 +313,8 @@ function bit_converter.bytes_to_uint16(bytes, order)
return return
bit.bor( bit.bor(
bit.lshift(bytes[1], 8), bit.lshift(bytes[2], 8),
bytes[2], 0) bytes[1], 0)
end end
function bit_converter.bytes_to_int64(bytes, order) function bit_converter.bytes_to_int64(bytes, order)

View File

@ -144,31 +144,31 @@ function data_buffer:put_number(num)
if math.floor(num) ~= num then if math.floor(num) ~= num then
type = TYPE_FLOAT64 type = TYPE_FLOAT64
bytes = bit_converter.float64_to_bytes(num) bytes = bit_converter.float64_to_bytes(num, self.order)
elseif num == 0 then elseif num == 0 then
type = TYPE_ZERO type = TYPE_ZERO
bytes = { } bytes = { }
elseif num > 0 then elseif num > 0 then
if num <= MAX_UINT16 then if num <= MAX_UINT16 then
type = TYPE_UINT16 type = TYPE_UINT16
bytes = bit_converter.uint16_to_bytes(num) bytes = bit_converter.uint16_to_bytes(num, self.order)
elseif num <= MAX_UINT32 then elseif num <= MAX_UINT32 then
type = TYPE_UINT32 type = TYPE_UINT32
bytes = bit_converter.uint32_to_bytes(num) bytes = bit_converter.uint32_to_bytes(num, self.order)
elseif num <= MAX_INT64 then elseif num <= MAX_INT64 then
type = TYPE_INT64 type = TYPE_INT64
bytes = bit_converter.int64_to_bytes(num) bytes = bit_converter.int64_to_bytes(num, self.order)
end end
elseif num < 0 then elseif num < 0 then
if num >= MIN_INT16 then if num >= MIN_INT16 then
type = TYPE_SINT16 type = TYPE_SINT16
bytes = bit_converter.sint16_to_bytes(num) bytes = bit_converter.sint16_to_bytes(num, self.order)
elseif num >= MIN_INT32 then elseif num >= MIN_INT32 then
type = TYPE_SINT32 type = TYPE_SINT32
bytes = bit_converter.sint32_to_bytes(num) bytes = bit_converter.sint32_to_bytes(num, self.order)
elseif num >= MIN_INT64 then elseif num >= MIN_INT64 then
type = TYPE_INT64 type = TYPE_INT64
bytes = bit_converter.int64_to_bytes(num) bytes = bit_converter.int64_to_bytes(num, self.order)
end end
end end

View File

@ -68,6 +68,22 @@ local Entity = {__index={
def_index=function(self) return entities.get_def(self.eid) end, def_index=function(self) return entities.get_def(self.eid) end,
def_name=function(self) return entities.def_name(entities.get_def(self.eid)) end, def_name=function(self) return entities.def_name(entities.get_def(self.eid)) end,
get_player=function(self) return entities.get_player(self.eid) end, get_player=function(self) return entities.get_player(self.eid) end,
set_enabled=function(self, name, flag)
local comp = self.components[name]
if comp then
if flag then
if comp.__disabled and comp.on_enable then
comp.on_enable()
end
comp.__disabled = nil
else
if not comp.__disabled and comp.on_disable then
comp.on_disable()
end
comp.__disabled = true
end
end
end,
}} }}
local entities = {} local entities = {}
@ -99,7 +115,7 @@ return {
end end
for _, component in pairs(entity.components) do for _, component in pairs(entity.components) do
local callback = component.on_update local callback = component.on_update
if callback then if not component.__disabled and callback then
local result, err = pcall(callback, tps) local result, err = pcall(callback, tps)
if err then if err then
debug.error(err) debug.error(err)
@ -113,7 +129,7 @@ return {
for _,entity in pairs(entities) do for _,entity in pairs(entities) do
for _, component in pairs(entity.components) do for _, component in pairs(entity.components) do
local callback = component.on_render local callback = component.on_render
if callback then if not component.__disabled and callback then
local result, err = pcall(callback, delta) local result, err = pcall(callback, delta)
if err then if err then
debug.error(err) debug.error(err)

View File

@ -37,7 +37,10 @@ local function complete_app_lib(app)
app.tick = coroutine.yield app.tick = coroutine.yield
app.get_version = core.get_version app.get_version = core.get_version
app.get_setting_info = core.get_setting_info app.get_setting_info = core.get_setting_info
app.load_content = core.load_content app.load_content = function()
core.load_content()
app.tick()
end
app.reset_content = core.reset_content app.reset_content = core.reset_content
app.is_content_loaded = core.is_content_loaded app.is_content_loaded = core.is_content_loaded
@ -416,7 +419,18 @@ end
function start_coroutine(chunk, name) function start_coroutine(chunk, name)
local co = coroutine.create(function() local co = coroutine.create(function()
local status, error = xpcall(chunk, __vc__error) local status, error = xpcall(chunk, function(...)
gui.alert(debug.traceback(), function()
if world.is_open() then
__vc_app.close_world()
else
__vc_app.reset_content()
menu:reset()
menu.page = "main"
end
end)
return ...
end)
if not status then if not status then
debug.error(error) debug.error(error)
end end

View File

@ -27,6 +27,7 @@ inline constexpr blockid_t BLOCK_OBSTACLE = 1;
inline constexpr blockid_t BLOCK_STRUCT_AIR = 2; inline constexpr blockid_t BLOCK_STRUCT_AIR = 2;
inline constexpr itemid_t ITEM_EMPTY = 0; inline constexpr itemid_t ITEM_EMPTY = 0;
inline constexpr entityid_t ENTITY_NONE = 0; inline constexpr entityid_t ENTITY_NONE = 0;
inline constexpr entityid_t ENTITY_AUTO = std::numeric_limits<entityid_t>::max();
inline constexpr int CHUNK_W = 16; inline constexpr int CHUNK_W = 16;
inline constexpr int CHUNK_H = 256; inline constexpr int CHUNK_H = 256;

View File

@ -104,6 +104,9 @@ namespace dv {
} }
boolean_t value::asBoolean() const { boolean_t value::asBoolean() const {
if (type == value_type::none) {
return false;
}
check_type(type, value_type::boolean); check_type(type, value_type::boolean);
return val.boolean; return val.boolean;
} }

View File

@ -199,6 +199,7 @@ void Engine::updateFrontend() {
audio::update(delta); audio::update(delta);
gui->act(delta, Viewport(Window::width, Window::height)); gui->act(delta, Viewport(Window::width, Window::height));
screen->update(delta); screen->update(delta);
gui->postAct();
} }
void Engine::nextFrame() { void Engine::nextFrame() {
@ -217,7 +218,6 @@ void Engine::renderFrame() {
Viewport viewport(Window::width, Window::height); Viewport viewport(Window::width, Window::height);
DrawContext ctx(nullptr, viewport, nullptr); DrawContext ctx(nullptr, viewport, nullptr);
gui->draw(ctx, *assets); gui->draw(ctx, *assets);
gui->postAct();
} }
void Engine::saveSettings() { void Engine::saveSettings() {

View File

@ -202,7 +202,7 @@ void GUI::act(float delta, const Viewport& vp) {
void GUI::postAct() { void GUI::postAct() {
while (!postRunnables.empty()) { while (!postRunnables.empty()) {
runnable callback = postRunnables.back(); runnable callback = postRunnables.front();
postRunnables.pop(); postRunnables.pop();
callback(); callback();
} }

View File

@ -53,6 +53,7 @@ void Panel::cropToContent() {
void Panel::fullRefresh() { void Panel::fullRefresh() {
refresh(); refresh();
cropToContent(); cropToContent();
reposition();
Container::fullRefresh(); Container::fullRefresh();
} }

View File

@ -826,7 +826,7 @@ void TextBox::setCaret(size_t position) {
scrolled(-glm::ceil(offset/static_cast<double>(scrollStep)+0.5f)); scrolled(-glm::ceil(offset/static_cast<double>(scrollStep)+0.5f));
} }
uint lcaret = caret - label->getTextLineOffset(line); uint lcaret = caret - label->getTextLineOffset(line);
int realoffset = font->calcWidth(input, lcaret)-int(textOffset)+2; int realoffset = font->calcWidth(input, lcaret)-int(textOffset) - padding.x;
if (realoffset-width > 0) { if (realoffset-width > 0) {
setTextOffset(textOffset + realoffset-width); setTextOffset(textOffset + realoffset-width);
} else if (realoffset < 0) { } else if (realoffset < 0) {

View File

@ -34,13 +34,14 @@ void guiutil::alert(
auto panel = std::make_shared<Panel>(glm::vec2(500, 300), glm::vec4(4.0f), 4.0f); auto panel = std::make_shared<Panel>(glm::vec2(500, 300), glm::vec4(4.0f), 4.0f);
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f)); panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
auto menu = engine.getGUI()->getMenu(); auto menuPtr = engine.getGUI()->getMenu();
runnable on_hidden_final = [on_hidden, menu, &engine]() { auto& menu = *menuPtr;
menu->removePage("<alert>"); runnable on_hidden_final = [on_hidden, &menu, &engine]() {
menu.removePage("<alert>");
if (on_hidden) { if (on_hidden) {
on_hidden(); on_hidden();
} else { } else {
menu->back(); menu.back();
} }
}; };
@ -50,21 +51,21 @@ void guiutil::alert(
panel->add(label); panel->add(label);
panel->add(std::make_shared<Button>( panel->add(std::make_shared<Button>(
langs::get(L"Ok"), glm::vec4(10.f), langs::get(L"Ok"), glm::vec4(10.f),
[=](GUI*) { [on_hidden_final](GUI*) {
on_hidden_final(); on_hidden_final();
} }
)); ));
panel->refresh(); panel->refresh();
panel->keepAlive(Events::keyCallbacks[keycode::ENTER].add([=](){ panel->keepAlive(Events::keyCallbacks[keycode::ENTER].add([on_hidden_final](){
on_hidden_final(); on_hidden_final();
return true; return true;
})); }));
panel->keepAlive(Events::keyCallbacks[keycode::ESCAPE].add([=](){ panel->keepAlive(Events::keyCallbacks[keycode::ESCAPE].add([on_hidden_final](){
on_hidden_final(); on_hidden_final();
return true; return true;
})); }));
menu->addPage("<alert>", panel, true); menu.addPage("<alert>", panel, true);
menu->setPage("<alert>"); menu.setPage("<alert>");
} }
void guiutil::confirm( void guiutil::confirm(

View File

@ -4,6 +4,7 @@
#include "typedefs.hpp" #include "typedefs.hpp"
#include <memory> #include <memory>
#include <cstring>
inline constexpr int LIGHTMAP_DATA_LEN = CHUNK_VOL/2; inline constexpr int LIGHTMAP_DATA_LEN = CHUNK_VOL/2;
@ -17,6 +18,10 @@ public:
void set(const light_t* map); void set(const light_t* map);
void clear() {
std::memset(map, 0, sizeof(map));
}
inline unsigned short get(int x, int y, int z) const { inline unsigned short get(int x, int y, int z) const {
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x]); return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x]);
} }

View File

@ -229,7 +229,9 @@ static int l_set_entity(lua::State* L) {
if (player == nullptr) { if (player == nullptr) {
return 0; return 0;
} }
if (auto entity = get_entity(L, 2)) { if (lua::isnumber(L, 2)) {
player->setEntity(lua::tointeger(L, 2));
} else if (auto entity = get_entity(L, 2)) {
player->setEntity(entity->getUID()); player->setEntity(entity->getUID());
} }
return 0; return 0;

View File

@ -148,12 +148,12 @@ static void integrate_chunk_client(Chunk& chunk) {
int x = chunk.x; int x = chunk.x;
int z = chunk.z; int z = chunk.z;
auto chunksController = controller->getChunksController(); auto chunksController = controller->getChunksController();
Lighting& lighting = *chunksController->lighting; Lighting& lighting = *chunksController->lighting;
chunk.flags.loadedLights = false; chunk.flags.loadedLights = false;
chunk.flags.lighted = false; chunk.flags.lighted = false;
chunk.lightmap.clear();
Lighting::prebuildSkyLight(chunk, *indices); Lighting::prebuildSkyLight(chunk, *indices);
lighting.onChunkLoaded(x, z, true);
for (int lz = -1; lz <= 1; lz++) { for (int lz = -1; lz <= 1; lz++) {
for (int lx = -1; lx <= 1; lx++) { for (int lx = -1; lx <= 1; lx++) {
@ -162,7 +162,6 @@ static void integrate_chunk_client(Chunk& chunk) {
} }
if (auto other = level->chunks->getChunk(x + lx, z + lz)) { if (auto other = level->chunks->getChunk(x + lx, z + lz)) {
other->flags.modified = true; other->flags.modified = true;
lighting.onChunkLoaded(x - 1, z, true);
} }
} }
} }

View File

@ -22,6 +22,9 @@ namespace lua {
inline void pop(lua::State* L, int n = 1) { inline void pop(lua::State* L, int n = 1) {
#ifndef NDEBUG #ifndef NDEBUG
if (n < 0) {
abort();
}
if (lua_gettop(L) < n) { if (lua_gettop(L) < n) {
abort(); abort();
} }

View File

@ -86,7 +86,10 @@ public:
} }
void update() override { void update() override {
if (lua::getglobal(L, "__vc_resume_coroutine")) { if (id == 0) {
return;
}
if (lua::requireglobal(L, "__vc_resume_coroutine")) {
lua::pushinteger(L, id); lua::pushinteger(L, id);
if (lua::call(L, 1)) { if (lua::call(L, 1)) {
alive = lua::toboolean(L, -1); alive = lua::toboolean(L, -1);
@ -102,10 +105,10 @@ public:
} }
void terminate() override { void terminate() override {
if (lua::getglobal(L, "__vc_stop_coroutine")) { lua::requireglobal(L, "__vc_stop_coroutine");
lua::pushinteger(L, id); lua::pushinteger(L, id);
lua::pop(L, lua::call(L, 1)); lua::pop(L, lua::call(L, 1));
} id = 0;
} }
}; };
@ -614,6 +617,10 @@ static void process_entity_callback(
) { ) {
auto L = lua::get_main_state(); auto L = lua::get_main_state();
lua::pushenv(L, *env); lua::pushenv(L, *env);
if (lua::hasfield(L, "__disabled")) {
lua::pop(L);
return;
}
if (lua::getfield(L, name)) { if (lua::getfield(L, name)) {
if (args) { if (args) {
lua::call_nothrow(L, args(L), 0); lua::call_nothrow(L, args(L), 0);

View File

@ -62,7 +62,7 @@ Player::Player(
Player::~Player() = default; Player::~Player() = default;
void Player::updateEntity() { void Player::updateEntity() {
if (eid == 0) { if (eid == ENTITY_AUTO) {
auto& def = level.content.entities.require("base:player"); auto& def = level.content.entities.require("base:player");
eid = level.entities->spawn(def, getPosition()); eid = level.entities->spawn(def, getPosition());
if (auto entity = level.entities->get(eid)) { if (auto entity = level.entities->get(eid)) {
@ -73,10 +73,10 @@ void Player::updateEntity() {
if (auto entity = level.entities->get(eid)) { if (auto entity = level.entities->get(eid)) {
entity->setPlayer(id); entity->setPlayer(id);
} }
} else if (chunks->getChunkByVoxel(position)) { } else if (chunks->getChunkByVoxel(position) && eid != ENTITY_NONE) {
logger.error() << "player entity despawned or deleted; " logger.error() << "player entity despawned or deleted; "
"will be respawned"; "will be respawned";
eid = 0; eid = ENTITY_AUTO;
} }
} }

View File

@ -54,7 +54,7 @@ class Player : public Serializable {
bool infiniteItems = true; bool infiniteItems = true;
bool instantDestruction = true; bool instantDestruction = true;
bool loadingChunks = true; bool loadingChunks = true;
entityid_t eid; entityid_t eid = ENTITY_AUTO;
entityid_t selectedEid = 0; entityid_t selectedEid = 0;
glm::vec3 rotation {}; glm::vec3 rotation {};

View File

@ -37,7 +37,7 @@ Player* Players::create(int64_t id) {
glm::vec3(0, DEF_PLAYER_Y, 0), glm::vec3(0, DEF_PLAYER_Y, 0),
DEF_PLAYER_SPEED, DEF_PLAYER_SPEED,
level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), level.inventories->create(DEF_PLAYER_INVENTORY_SIZE),
0 ENTITY_AUTO
); );
auto player = playerPtr.get(); auto player = playerPtr.get();
add(std::move(playerPtr)); add(std::move(playerPtr));
@ -92,7 +92,7 @@ void Players::deserialize(const dv::value& src) {
glm::vec3(0, DEF_PLAYER_Y, 0), glm::vec3(0, DEF_PLAYER_Y, 0),
DEF_PLAYER_SPEED, DEF_PLAYER_SPEED,
level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), level.inventories->create(DEF_PLAYER_INVENTORY_SIZE),
0 ENTITY_AUTO
); );
auto player = playerPtr.get(); auto player = playerPtr.get();
player->deserialize(playerMap); player->deserialize(playerMap);