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
git clone https://github.com/skypjack/entt.git
cd entt/build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake -DCMAKE_BUILD_TYPE=Release -DENTT_INSTALL=on ..
sudo make install
cd ../..
- name: Configure

View File

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

View File

@ -14,7 +14,7 @@
```sh
git clone https://github.com/skypjack/entt.git
cd entt/build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake -DCMAKE_BUILD_TYPE=Release -DENTT_INSTALL=on ..
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.
```lua
rules.listen(
rules.listen(
-- rule name
name: str,
-- value change handler function

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@
</container>
<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
id='log'
color='0'
@ -20,7 +20,7 @@
margin='0'
editable='false'
multiline='true'
size-func="gui.get_viewport()[1],40"
size-func="gui.get_viewport()[1]-350,40"
gravity="bottom-left"
markup="md"
></textbox>

View File

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

View File

@ -313,8 +313,8 @@ function bit_converter.bytes_to_uint16(bytes, order)
return
bit.bor(
bit.lshift(bytes[1], 8),
bytes[2], 0)
bit.lshift(bytes[2], 8),
bytes[1], 0)
end
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
type = TYPE_FLOAT64
bytes = bit_converter.float64_to_bytes(num)
bytes = bit_converter.float64_to_bytes(num, self.order)
elseif num == 0 then
type = TYPE_ZERO
bytes = { }
elseif num > 0 then
if num <= MAX_UINT16 then
type = TYPE_UINT16
bytes = bit_converter.uint16_to_bytes(num)
bytes = bit_converter.uint16_to_bytes(num, self.order)
elseif num <= MAX_UINT32 then
type = TYPE_UINT32
bytes = bit_converter.uint32_to_bytes(num)
bytes = bit_converter.uint32_to_bytes(num, self.order)
elseif num <= MAX_INT64 then
type = TYPE_INT64
bytes = bit_converter.int64_to_bytes(num)
bytes = bit_converter.int64_to_bytes(num, self.order)
end
elseif num < 0 then
if num >= MIN_INT16 then
type = TYPE_SINT16
bytes = bit_converter.sint16_to_bytes(num)
bytes = bit_converter.sint16_to_bytes(num, self.order)
elseif num >= MIN_INT32 then
type = TYPE_SINT32
bytes = bit_converter.sint32_to_bytes(num)
bytes = bit_converter.sint32_to_bytes(num, self.order)
elseif num >= MIN_INT64 then
type = TYPE_INT64
bytes = bit_converter.int64_to_bytes(num)
bytes = bit_converter.int64_to_bytes(num, self.order)
end
end

View File

@ -68,6 +68,22 @@ local Entity = {__index={
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,
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 = {}
@ -99,7 +115,7 @@ return {
end
for _, component in pairs(entity.components) do
local callback = component.on_update
if callback then
if not component.__disabled and callback then
local result, err = pcall(callback, tps)
if err then
debug.error(err)
@ -113,7 +129,7 @@ return {
for _,entity in pairs(entities) do
for _, component in pairs(entity.components) do
local callback = component.on_render
if callback then
if not component.__disabled and callback then
local result, err = pcall(callback, delta)
if err then
debug.error(err)

View File

@ -37,7 +37,10 @@ local function complete_app_lib(app)
app.tick = coroutine.yield
app.get_version = core.get_version
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.is_content_loaded = core.is_content_loaded
@ -416,7 +419,18 @@ end
function start_coroutine(chunk, name)
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
debug.error(error)
end

View File

@ -27,6 +27,7 @@ inline constexpr blockid_t BLOCK_OBSTACLE = 1;
inline constexpr blockid_t BLOCK_STRUCT_AIR = 2;
inline constexpr itemid_t ITEM_EMPTY = 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_H = 256;

View File

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

View File

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

View File

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

View File

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

View File

@ -826,7 +826,7 @@ void TextBox::setCaret(size_t position) {
scrolled(-glm::ceil(offset/static_cast<double>(scrollStep)+0.5f));
}
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) {
setTextOffset(textOffset + realoffset-width);
} 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);
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
auto menu = engine.getGUI()->getMenu();
runnable on_hidden_final = [on_hidden, menu, &engine]() {
menu->removePage("<alert>");
auto menuPtr = engine.getGUI()->getMenu();
auto& menu = *menuPtr;
runnable on_hidden_final = [on_hidden, &menu, &engine]() {
menu.removePage("<alert>");
if (on_hidden) {
on_hidden();
} else {
menu->back();
menu.back();
}
};
@ -50,21 +51,21 @@ void guiutil::alert(
panel->add(label);
panel->add(std::make_shared<Button>(
langs::get(L"Ok"), glm::vec4(10.f),
[=](GUI*) {
[on_hidden_final](GUI*) {
on_hidden_final();
}
));
panel->refresh();
panel->keepAlive(Events::keyCallbacks[keycode::ENTER].add([=](){
panel->keepAlive(Events::keyCallbacks[keycode::ENTER].add([on_hidden_final](){
on_hidden_final();
return true;
}));
panel->keepAlive(Events::keyCallbacks[keycode::ESCAPE].add([=](){
panel->keepAlive(Events::keyCallbacks[keycode::ESCAPE].add([on_hidden_final](){
on_hidden_final();
return true;
}));
menu->addPage("<alert>", panel, true);
menu->setPage("<alert>");
menu.addPage("<alert>", panel, true);
menu.setPage("<alert>");
}
void guiutil::confirm(

View File

@ -4,6 +4,7 @@
#include "typedefs.hpp"
#include <memory>
#include <cstring>
inline constexpr int LIGHTMAP_DATA_LEN = CHUNK_VOL/2;
@ -17,6 +18,10 @@ public:
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 {
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) {
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());
}
return 0;

View File

@ -148,12 +148,12 @@ static void integrate_chunk_client(Chunk& chunk) {
int x = chunk.x;
int z = chunk.z;
auto chunksController = controller->getChunksController();
Lighting& lighting = *chunksController->lighting;
chunk.flags.loadedLights = false;
chunk.flags.lighted = false;
chunk.lightmap.clear();
Lighting::prebuildSkyLight(chunk, *indices);
lighting.onChunkLoaded(x, z, true);
for (int lz = -1; lz <= 1; lz++) {
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)) {
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) {
#ifndef NDEBUG
if (n < 0) {
abort();
}
if (lua_gettop(L) < n) {
abort();
}

View File

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

View File

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

View File

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

View File

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