Merge branch 'main' into fix-assets-pipeline

This commit is contained in:
MihailRis 2026-07-20 20:23:11 +03:00
commit f30b5f84d0
24 changed files with 339 additions and 66 deletions

View file

@ -49,9 +49,9 @@ static util::Buffer<ubyte> write_to_memory(uint width, uint height, const ubyte*
png_write_info(png_ptr, info_ptr);
auto row = std::make_unique<png_byte[]>(pixsize * width);
for (uint y = 0; y < height; y++) {
for (uint x = 0; x < width; x++) {
for (uint i = 0; i < pixsize; i++) {
for (int y = height-1; y >= 0; y--) {
for (int x = 0; x < width; x++) {
for (int i = 0; i < pixsize; i++) {
row[x * pixsize + i] =
(png_byte)data[(y * width + x) * pixsize + i];
}

View file

@ -1,5 +1,7 @@
#include "ImageData.hpp"
#include "debug/Logger.hpp"
#include <glm/glm.hpp>
#include <assert.h>
#include <stdexcept>
@ -7,6 +9,8 @@
#include <cmath>
#include <algorithm>
static debug::Logger logger("image-data");
ImageData::ImageData(ImageFormat format, uint width, uint height)
: format(format), width(width), height(height) {
size_t pixsize;
@ -106,47 +110,83 @@ std::unique_ptr<ImageData> ImageData::cropped(int x, int y, int width, int heigh
return subImage;
}
static bool clip_line(int& x1, int& y1, int& x2, int& y2, int width, int height) {
const int left = 0;
const int right = width;
const int bottom = 0;
const int top = height;
static bool clip_line(
int& x0, int& y0, int& x1, int& y1, int width, int height
) {
if (width <= 0 || height <= 0) {
return false;
}
constexpr int INSIDE = 0;
constexpr int LEFT = 1;
constexpr int RIGHT = 2;
constexpr int BOTTOM = 4;
constexpr int TOP = 8;
int dx = x2 - x1;
int dy = y2 - y1;
const int xmin = 0;
const int ymin = 0;
const int xmax = width - 1;
const int ymax = height - 1;
float t0 = 0.0f;
float t1 = 1.0f;
auto outcode = [&](int x, int y) {
int code = INSIDE;
auto clip = [](int p, int q, float& t0, float& t1) {
if (p == 0) {
return q >= 0;
}
float t = static_cast<float>(q) / p;
if (p < 0) {
if (t > t1) return false;
if (t > t0) t0 = t;
} else {
if (t < t0) return false;
if (t < t1) t1 = t;
}
return true;
if (x < xmin)
code |= LEFT;
else if (x > xmax)
code |= RIGHT;
if (y < ymin)
code |= BOTTOM;
else if (y > ymax)
code |= TOP;
return code;
};
if (!clip(-dx, x1 - left, t0, t1)) return false;
if (!clip( dx, right - x1, t0, t1)) return false;
if (!clip(-dy, y1 - bottom, t0, t1)) return false;
if (!clip( dy, top - y1, t0, t1)) return false;
int c0 = outcode(x0, y0);
int c1 = outcode(x1, y1);
if (t1 < 1.0f) {
x2 = x1 + static_cast<int>(std::round(t1 * dx));
y2 = y1 + static_cast<int>(std::round(t1 * dy));
while (true) {
if (!(c0 | c1)) {
return true;
}
if (c0 & c1) {
return false;
}
const int out = c0 ? c0 : c1;
double x = 0.0;
double y = 0.0;
if (out & TOP) {
y = ymax;
x = x0 + (x1 - x0) * static_cast<double>(ymax - y0) / (y1 - y0);
} else if (out & BOTTOM) {
y = ymin;
x = x0 + (x1 - x0) * static_cast<double>(ymin - y0) / (y1 - y0);
} else if (out & RIGHT) {
x = xmax;
y = y0 + (y1 - y0) * static_cast<double>(xmax - x0) / (x1 - x0);
} else { // LEFT
x = xmin;
y = y0 + (y1 - y0) * static_cast<double>(xmin - x0) / (x1 - x0);
}
if (out == c0) {
x0 = std::clamp(static_cast<int>(std::lround(x)), xmin, xmax);
y0 = std::clamp(static_cast<int>(std::lround(y)), ymin, ymax);
c0 = outcode(x0, y0);
} else {
x1 = std::clamp(static_cast<int>(std::lround(x)), xmin, xmax);
y1 = std::clamp(static_cast<int>(std::lround(y)), ymin, ymax);
c1 = outcode(x1, y1);
}
}
if (t0 > 0.0f) {
x1 = x1 + static_cast<int>(std::round(t0 * dx));
y1 = y1 + static_cast<int>(std::round(t0 * dy));
}
return true;
}
static bool is_point_outside(int x, int y, int width, int height) {
return x < 0 || y < 0 || x >= width || y >= height;
}
template<uint channels>
@ -155,11 +195,24 @@ static void draw_line(ImageData& image, int x1, int y1, int x2, int y2, const gl
uint width = image.getWidth();
uint height = image.getHeight();
glm::ivec4 init {x1, y1, x2, y2};
if ((x1 < 0 || x1 >= width || x2 < 0 || x2 >= width ||
y1 < 0 || y1 >= height || y2 < 0 || y2 >= height) &&
!clip_line(x1, y1, x2, y2, width, height)) {
return;
}
// spam info for bug report
if (is_point_outside(x1, y1, width, height) || is_point_outside(x2, y2, width, height)) {
logger.warning() << "clip_line fault: [" << init.x << ", " << init.y
<< "] - [" << init.z << ", " << init.w << "] --> ["
<< x1 << ", " << y1 << "] - [" << x2 << ", " << y2
<< "]";
x1 = glm::clamp(x1, 0, static_cast<int>(width) - 1);
y1 = glm::clamp(y1, 0, static_cast<int>(height) - 1);
x2 = glm::clamp(x2, 0, static_cast<int>(width) - 1);
y2 = glm::clamp(y2, 0, static_cast<int>(height) - 1);
}
int dx = std::abs(x2 - x1);
int dy = -std::abs(y2 - y1);

View file

@ -55,6 +55,16 @@ public:
return fields;
}
void setFields(dv::value&& table, bool clear) {
if (clear) {
fields = std::move(table);
return;
}
for (auto&& [key, value] : table.asObject()) {
fields[std::move(key)] = std::move(value);
}
}
bool hasFields() const {
return fields != nullptr;
}

View file

@ -82,7 +82,6 @@ void LevelController::update(float delta, bool pause) {
continue;
}
player->rotationInterpolation.updateTimer(delta);
player->updateEntity();
glm::vec3 position = player->getPosition();
player->chunks->configure(
glm::floor(position.x),
@ -96,9 +95,9 @@ void LevelController::update(float delta, bool pause) {
*player,
player.get() == clientPlayer
);
player->updateEntity();
}
if (!pause) {
// update all objects that needed
blocks->update(delta, settings.chunks.padding.get());
level->entities->update(delta);
for (const auto& [_, player] : *level->players) {

View file

@ -237,6 +237,14 @@ static int l_get_all_data(lua::State* L, ItemStack& stack) {
return lua::pushvalue(L, stack.getFields());
}
static int l_set_all_data(lua::State* L, ItemStack& stack) {
if (!lua::istable(L, 3)) {
throw std::runtime_error("table expected as argument 1");
}
stack.setFields(lua::tovalue(L, 3), lua::toboolean(L, 4));
return 0;
}
static int l_has_data(lua::State* L, ItemStack& stack) {
auto key = lua::tostring(L, 3);
if (key == nullptr) {
@ -267,6 +275,7 @@ const luaL_Reg inventorylib[] = {
{"get_data", lua::wrap<wrap_slot<l_get_data>>},
{"set_data", lua::wrap<wrap_slot<l_set_data>>},
{"get_all_data", lua::wrap<wrap_slot<l_get_all_data>>},
{"set_all_data", lua::wrap<wrap_slot<l_set_all_data>>},
{"has_data", lua::wrap<wrap_slot<l_has_data>>},
{"create", lua::wrap<l_create>},
{"remove", lua::wrap<l_remove>},

View file

@ -81,16 +81,17 @@ union RGBA {
uint8_t arr[4];
uint32_t rgba;
};
static_assert(sizeof(RGBA) == 4);
static RGBA* get_at(const ImageData& data, uint index) {
if (index >= data.getWidth() * data.getHeight()) {
return nullptr;
}
static RGBA* get_at(const ImageData& data, size_t index) {
return reinterpret_cast<RGBA*>(data.getData() + index * sizeof(RGBA));
}
static RGBA* get_at(const ImageData& data, uint x, uint y) {
return get_at(data, y * data.getWidth() + x);
if (x >= data.getWidth() || y >= data.getHeight()) {
return nullptr;
}
return get_at(data, static_cast<size_t>(y) * data.getWidth() + x);
}
static RGBA* get_at(State* L, uint x, uint y) {

View file

@ -142,6 +142,7 @@ namespace scripting {
void on_entity_grounded(const Entity& entity, float force);
void on_entity_fall(const Entity& entity);
void on_entity_save(const Entity& entity);
void on_entity_player_set(const Entity& entity, int64_t pid);
void on_entities_update(int tps, int parts, int part);
void on_entities_physics_update(float delta);
void on_entities_render(float delta);

View file

@ -71,6 +71,7 @@ static void init_component_events(
funcsset.on_aim_off = lua::hasfield(L, "on_aim_off");
funcsset.on_attacked = lua::hasfield(L, "on_attacked");
funcsset.on_used = lua::hasfield(L, "on_used");
funcsset.on_player_set = lua::hasfield(L, "on_player_set");
lua::pop(L);
}
@ -238,6 +239,15 @@ void scripting::on_entity_save(const Entity& entity) {
);
}
void scripting::on_entity_player_set(const Entity& entity, int64_t pid) {
process_entity_callback(
entity,
"on_player_set",
&EntityFuncsSet::on_player_set,
[pid](auto L) { return lua::pushinteger(L, pid); }
);
}
void scripting::on_sensor_enter(
const Entity& entity, size_t index, entityid_t oid
) {

View file

@ -113,6 +113,11 @@ int64_t Entity::getPlayer() const {
}
void Entity::setPlayer(int64_t id) {
registry.get<EntityId>(entity).player = id;
auto& eid = registry.get<EntityId>(entity);
if (eid.player == id) {
return;
}
eid.player = id;
scripting::on_entity_player_set(*this, id);
}

View file

@ -81,7 +81,7 @@ void Player::updateEntity() {
}
}
Hitbox* Player::getHitbox() {
Hitbox* Player::getHitbox() const {
if (auto entity = level.entities->get(eid)) {
return &entity->getRigidbody().hitbox;
}

View file

@ -135,7 +135,7 @@ public:
bool isCurrentCameraBuiltin() const;
Hitbox* getHitbox();
Hitbox* getHitbox() const;
void setSpawnPoint(glm::vec3 point);
glm::vec3 getSpawnPoint() const;

View file

@ -17,6 +17,7 @@ struct EntityFuncsSet {
bool on_aim_off;
bool on_attacked;
bool on_used;
bool on_player_set;
};
struct UserComponent {

View file

@ -88,12 +88,22 @@ void Skeleton::deserialize(const dv::value& root) {
void Skeleton::setConfig(std::shared_ptr<const SkeletonConfig> rigConfig) {
config = std::move(rigConfig);
const auto& bones = config->getBones();
pose.matrices.resize(
config->getBones().size(), glm::mat4(1.0f)
bones.size(), glm::mat4(1.0f)
);
calculated.matrices.resize(
config->getBones().size(), glm::mat4(1.0f)
bones.size(), glm::mat4(1.0f)
);
modelOverrides.resize(bones.size());
flags.resize(bones.size());
for (size_t i = 0; i < bones.size(); i++) {
flags[i].visible = true;
}
}
static void get_all_nodes(std::vector<Bone*>& nodes, Bone* node) {

View file

@ -309,7 +309,9 @@ static inline voxel* raycast_blocks(
} else {
iend = {ix, iy, iz};
norm = {0, 0, 0};
norm[steppedIndex] = -step[steppedIndex];
if (steppedIndex != -1) {
norm[steppedIndex] = -step[steppedIndex];
}
return voxel;
}
}