Merge pull request #735 from MihailRis/fixes

0.30.7 patch
This commit is contained in:
MihailRis 2025-12-16 01:05:48 +03:00 • committed by GitHub
commit 66d85b0ae6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 105 additions and 54 deletions

View file

@ -9,6 +9,7 @@ block.__perform_ticks = function(delta)
for id, entry in pairs(updating_blocks) do for id, entry in pairs(updating_blocks) do
entry.timer = entry.timer + delta entry.timer = entry.timer + delta
local steps = math.floor(entry.timer / entry.delta * #entry / 3) local steps = math.floor(entry.timer / entry.delta * #entry / 3)
steps = math.min(steps, #entry / 3)
if steps == 0 then if steps == 0 then
goto continue goto continue
end end
@ -28,6 +29,7 @@ block.__perform_ticks = function(delta)
for id, queue in pairs(present_queues) do for id, queue in pairs(present_queues) do
queue.timer = queue.timer + delta queue.timer = queue.timer + delta
local steps = math.floor(queue.timer / queue.delta * #queue / 3) local steps = math.floor(queue.timer / queue.delta * #queue / 3)
steps = math.min(steps, #queue / 3)
if steps == 0 then if steps == 0 then
goto continue goto continue
end end

View file

@ -523,8 +523,10 @@ function __process_post_runnables()
fn_audio_reset_fetch_buffer() fn_audio_reset_fetch_buffer()
debug.pull_events() debug.pull_events()
network.__process_events() network.__process_events()
block.__process_register_events() if not hud or not hud.is_paused() then
block.__perform_ticks(time.delta()) block.__process_register_events()
block.__perform_ticks(time.delta())
end
end end
function time.post_runnable(runnable) function time.post_runnable(runnable)

View file

@ -15,9 +15,9 @@
#include "ContentPack.hpp" #include "ContentPack.hpp"
ContentIndices::ContentIndices( ContentIndices::ContentIndices(
ContentUnitIndices<Block> blocks, ContentUnitIndices<Block, blockid_t> blocks,
ContentUnitIndices<ItemDef> items, ContentUnitIndices<ItemDef, itemid_t> items,
ContentUnitIndices<EntityDef> entities ContentUnitIndices<EntityDef, entitydefid_t> entities
) )
: blocks(std::move(blocks)), : blocks(std::move(blocks)),
items(std::move(items)), items(std::move(items)),

View file

@ -36,48 +36,57 @@ public:
} }
}; };
template <class T> template <class T, typename IdType>
class ContentUnitIndices { class ContentUnitIndices {
std::vector<T*> defs; std::vector<T*> defs;
public: public:
ContentUnitIndices(std::vector<T*> defs) : defs(std::move(defs)) { ContentUnitIndices(std::vector<T*> defs) : defs(std::move(defs)) {
} }
inline const T* get(blockid_t id) const { const T* get(IdType id) const {
if (id >= defs.size()) { if (id >= defs.size()) {
return nullptr; return nullptr;
} }
return defs[id]; return defs[id];
} }
inline const T& require(blockid_t id) const { const T& require(IdType id) const {
return *defs.at(id); if (id >= defs.size()) {
invalidId(id);
}
return *defs[id];
} }
inline size_t count() const { size_t count() const {
return defs.size(); return defs.size();
} }
inline const auto& getIterable() const { const auto& getIterable() const {
return defs; return defs;
} }
inline const T* const* getDefs() const { const T* const* getDefs() const {
return defs.data(); return defs.data();
} }
private:
void invalidId(IdType id) const {
throw std::runtime_error(
"invalid content unit id: " + std::to_string(id)
);
}
}; };
/// @brief Runtime defs cache: indices /// @brief Runtime defs cache: indices
class ContentIndices { class ContentIndices {
public: public:
ContentUnitIndices<Block> blocks; ContentUnitIndices<Block, blockid_t> blocks;
ContentUnitIndices<ItemDef> items; ContentUnitIndices<ItemDef, itemid_t> items;
ContentUnitIndices<EntityDef> entities; ContentUnitIndices<EntityDef, entitydefid_t> entities;
ContentIndices( ContentIndices(
ContentUnitIndices<Block> blocks, ContentUnitIndices<Block, blockid_t> blocks,
ContentUnitIndices<ItemDef> items, ContentUnitIndices<ItemDef, itemid_t> items,
ContentUnitIndices<EntityDef> entities ContentUnitIndices<EntityDef, entitydefid_t> entities
); );
}; };

View file

@ -22,9 +22,9 @@ ContentReport::ContentReport(
regionsVersion(regionsVersion) { regionsVersion(regionsVersion) {
} }
template <class T> template <class T, typename IdType>
static constexpr size_t get_entries_count( static constexpr size_t get_entries_count(
const ContentUnitIndices<T>& indices, const dv::value& list const ContentUnitIndices<T, IdType>& indices, const dv::value& list
) { ) {
return list != nullptr ? std::max(list.size(), indices.count()) return list != nullptr ? std::max(list.size(), indices.count())
: indices.count(); : indices.count();

View file

@ -51,7 +51,7 @@ class ContentUnitLUT {
public: public:
ContentUnitLUT( ContentUnitLUT(
size_t count, size_t count,
const ContentUnitIndices<U>& unitIndices, const ContentUnitIndices<U, T>& unitIndices,
T missingValue, T missingValue,
ContentType type ContentType type
) )

View file

@ -404,22 +404,22 @@ void BlocksRenderer::blockCube(
} }
} else { } else {
if (isOpen(coord + Z, block, variant)) { if (isOpen(coord + Z, block, variant)) {
face(coord, X, Y, Z, texfaces[5], pickLight(coord + Z), lights); face(coord, X, Y, Z, texfaces[5], lights ? pickLight(coord + Z) : glm::vec4(1,1,1,0), lights);
} }
if (isOpen(coord - Z, block, variant)) { if (isOpen(coord - Z, block, variant)) {
face(coord, -X, Y, -Z, texfaces[4], pickLight(coord - Z), lights); face(coord, -X, Y, -Z, texfaces[4], lights ? pickLight(coord - Z) : glm::vec4(1,1,1,0), lights);
} }
if (isOpen(coord + Y, block, variant)) { if (isOpen(coord + Y, block, variant)) {
face(coord, X, -Z, Y, texfaces[3], pickLight(coord + Y), lights); face(coord, X, -Z, Y, texfaces[3], lights ? pickLight(coord + Y) : glm::vec4(1,1,1,0), lights);
} }
if (isOpen(coord - Y, block, variant)) { if (isOpen(coord - Y, block, variant)) {
face(coord, X, Z, -Y, texfaces[2], pickLight(coord - Y), lights); face(coord, X, Z, -Y, texfaces[2], lights ? pickLight(coord - Y) : glm::vec4(1,1,1,0), lights);
} }
if (isOpen(coord + X, block, variant)) { if (isOpen(coord + X, block, variant)) {
face(coord, -Z, Y, X, texfaces[1], pickLight(coord + X), lights); face(coord, -Z, Y, X, texfaces[1], lights ? pickLight(coord + X) : glm::vec4(1,1,1,0), lights);
} }
if (isOpen(coord - X, block, variant)) { if (isOpen(coord - X, block, variant)) {
face(coord, Z, Y, -X, texfaces[0], pickLight(coord - X), lights); face(coord, Z, Y, -X, texfaces[0], lights ? pickLight(coord - X) : glm::vec4(1,1,1,0), lights);
} }
} }
} }

View file

@ -146,11 +146,18 @@ void GUI::actMouse(float delta, const CursorState& cursor) {
} }
this->hover = hover; this->hover = hover;
auto node = hover; auto node = hover;
while (node) { while (node) {
if (mouseOver.find(hover) != mouseOver.end()) { if (std::find_if(
mouseOver.begin(),
mouseOver.end(),
[&hover](const std::weak_ptr<UINode>& weak) {
auto locked = weak.lock();
return locked && locked == hover;
}) != mouseOver.end()) {
break; break;
} }
mouseOver.insert(node); mouseOver.push_back(node);
node->setMouseOver(true); node->setMouseOver(true);
auto parent = node->getParent(); auto parent = node->getParent();
if (parent) { if (parent) {
@ -159,12 +166,14 @@ void GUI::actMouse(float delta, const CursorState& cursor) {
} }
for (auto it = mouseOver.begin(); it != mouseOver.end(); ) { for (auto it = mouseOver.begin(); it != mouseOver.end(); ) {
auto node = *it; auto node = it->lock();
if (node->isInside(cursor.pos)) { if (node) {
++it; if (node->isInside(cursor.pos)) {
continue; ++it;
continue;
}
node->setMouseOver(false);
} }
node->setMouseOver(false);
it = mouseOver.erase(it); it = mouseOver.erase(it);
} }
@ -270,6 +279,7 @@ void GUI::draw(const DrawContext& pctx, const Assets& assets) {
auto& page = menu->getCurrent(); auto& page = menu->getCurrent();
if (page.panel) { if (page.panel) {
menu->setSize(page.panel->getSize()); menu->setSize(page.panel->getSize());
page.panel->refresh();
if (auto panel = std::dynamic_pointer_cast<gui::Panel>(page.panel)) { if (auto panel = std::dynamic_pointer_cast<gui::Panel>(page.panel)) {
panel->cropToContent(); panel->cropToContent();
} }

View file

@ -81,7 +81,7 @@ namespace gui {
std::unique_ptr<Camera> uicamera; std::unique_ptr<Camera> uicamera;
std::shared_ptr<Menu> menu; std::shared_ptr<Menu> menu;
std::queue<runnable> postRunnables; std::queue<runnable> postRunnables;
std::set<std::shared_ptr<UINode>> mouseOver; std::vector<std::weak_ptr<UINode>> mouseOver;
PageLoaderFunc pagesLoader; PageLoaderFunc pagesLoader;

View file

@ -1,9 +1,10 @@
#include "Inventories.hpp" #include "Inventories.hpp"
#include <algorithm>
#include "world/Level.hpp" #include "world/Level.hpp"
#include "world/World.hpp" #include "world/World.hpp"
#include "content/Content.hpp"
#include <algorithm>
Inventories::Inventories(Level& level) : level(level) { Inventories::Inventories(Level& level) : level(level) {
} }
@ -32,8 +33,9 @@ std::shared_ptr<Inventory> Inventories::createVirtual(size_t size) {
}); });
} }
void Inventories::store(const std::shared_ptr<Inventory>& inv) { void Inventories::store(const std::shared_ptr<Inventory>& inventory) {
map[inv->getId()] = inv; inventory->check(*level.content.getIndices());
map[inventory->getId()] = inventory;
} }
void Inventories::remove(int64_t id) { void Inventories::remove(int64_t id) {

View file

@ -11,7 +11,7 @@ class Level;
using inventories_map = std::unordered_map<int64_t, std::shared_ptr<Inventory>>; using inventories_map = std::unordered_map<int64_t, std::shared_ptr<Inventory>>;
/* Inventories runtime storage */ /// @brief Inventories runtime storage
class Inventories { class Inventories {
Level& level; Level& level;
inventories_map map; inventories_map map;
@ -20,21 +20,22 @@ public:
Inventories(Level& level); Inventories(Level& level);
~Inventories(); ~Inventories();
/* Create new inventory with new id */ /// @brief Create new inventory with new id
std::shared_ptr<Inventory> create(size_t size); std::shared_ptr<Inventory> create(size_t size);
/* Create runtime-only inventory (has negative id) */ /// @brief Create runtime-only inventory (has negative id)
std::shared_ptr<Inventory> createVirtual(size_t size); std::shared_ptr<Inventory> createVirtual(size_t size);
/* Store inventory */ /// @brief Check and add inventory to the storage
void store(const std::shared_ptr<Inventory>& inv); void store(const std::shared_ptr<Inventory>& inv);
/* Remove inventory from map */ /// @brief Remove inventory from map
void remove(int64_t id); void remove(int64_t id);
/* Get inventory by id (works with both real and virtual)*/ /// @brief Get inventory by id (works with both real and virtual)
std::shared_ptr<Inventory> get(int64_t id); std::shared_ptr<Inventory> get(int64_t id);
/// @brief Create inventory non-virtual copy
std::shared_ptr<Inventory> clone(int64_t id); std::shared_ptr<Inventory> clone(int64_t id);
const inventories_map& getMap() const; const inventories_map& getMap() const;

View file

@ -1,6 +1,9 @@
#include "Inventory.hpp" #include "Inventory.hpp"
#include "content/ContentReport.hpp" #include "content/ContentReport.hpp"
#include "debug/Logger.hpp"
static debug::Logger logger("inventory");
Inventory::Inventory(int64_t id, size_t size) : id(id), slots(size) { Inventory::Inventory(int64_t id, size_t size) : id(id), slots(size) {
} }
@ -104,6 +107,22 @@ dv::value Inventory::serialize() const {
return map; return map;
} }
void Inventory::check(const ContentIndices& indices) {
for (size_t i = 0; i < slots.size(); i++) {
auto& slot = slots[i];
if (indices.items.get(slot.getItemId()) == nullptr) {
#ifdef NDEBUG
logger.error() << "invalid item id " << slot.getItemId()
<< " found in inventory #" << id << " slot #" << i
<< "; will reset";
slot.clear();
#else
abort();
#endif
}
}
}
void Inventory::convert(const ContentReport* report) { void Inventory::convert(const ContentReport* report) {
for (auto& slot : slots) { for (auto& slot : slots) {
itemid_t id = slot.getItemId(); itemid_t id = slot.getItemId();

View file

@ -39,6 +39,7 @@ public:
dv::value serialize() const override; dv::value serialize() const override;
void check(const ContentIndices& indices);
void convert(const ContentReport* report); void convert(const ContentReport* report);
static void convert(dv::value& data, const ContentReport* report); static void convert(dv::value& data, const ContentReport* report);

View file

@ -73,6 +73,7 @@ static int l_set(lua::State* L, ItemStack& item) {
if (!data.isObject() && data != nullptr) { if (!data.isObject() && data != nullptr) {
throw std::runtime_error("invalid data argument type (table expected)"); throw std::runtime_error("invalid data argument type (table expected)");
} }
validate_itemid(itemid);
item.set(ItemStack(itemid, count, std::move(data))); item.set(ItemStack(itemid, count, std::move(data)));
return 0; return 0;
} }

View file

@ -253,9 +253,9 @@ void scripting::process_post_runnables() {
} }
} }
template <class T> template <class T, typename IdType>
static int push_properties_tables( static int push_properties_tables(
lua::State* L, const ContentUnitIndices<T>& indices lua::State* L, const ContentUnitIndices<T, IdType>& indices
) { ) {
const auto units = indices.getDefs(); const auto units = indices.getDefs();
size_t size = indices.count(); size_t size = indices.count();

View file

@ -4,6 +4,7 @@
#include <glm/gtx/norm.hpp> #include <glm/gtx/norm.hpp>
#include "Player.hpp" #include "Player.hpp"
#include "content/Content.hpp"
#include "items/Inventories.hpp" #include "items/Inventories.hpp"
#include "world/Level.hpp" #include "world/Level.hpp"
#include "world/World.hpp" #include "world/World.hpp"
@ -147,6 +148,6 @@ void Players::deserialize(const dv::value& src) {
if (inventory->getId() == 0) { if (inventory->getId() == 0) {
inventory->setId(level.getWorld()->getNextInventoryId()); inventory->setId(level.getWorld()->getNextInventoryId());
} }
level.inventories->store(player->getInventory()); level.inventories->store(inventory);
} }
} }

View file

@ -21,6 +21,7 @@ using ubyte = uint8_t;
// content indices // content indices
using itemid_t = uint32_t; using itemid_t = uint32_t;
using blockid_t = uint16_t; using blockid_t = uint16_t;
using entitydefid_t = uint16_t;
using entityid_t = uint64_t; using entityid_t = uint64_t;
using itemcount_t = uint32_t; using itemcount_t = uint32_t;

View file

@ -70,7 +70,7 @@ void GlobalChunks::erase(int x, int z) {
static inline auto load_inventories( static inline auto load_inventories(
WorldRegions& regions, WorldRegions& regions,
const Chunk& chunk, const Chunk& chunk,
const ContentUnitIndices<Block>& defs const ContentUnitIndices<Block, blockid_t>& defs
) { ) {
auto invs = regions.fetchInventories(chunk.x, chunk.z); auto invs = regions.fetchInventories(chunk.x, chunk.z);
auto iterator = invs.begin(); auto iterator = invs.begin();

View file

@ -11,11 +11,13 @@
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
#include "typedefs.hpp"
class Block; class Block;
class Level; class Level;
class GlobalChunks; class GlobalChunks;
template <typename T> template <typename T, typename IdType>
class ContentUnitIndices; class ContentUnitIndices;
namespace voxels { namespace voxels {
@ -82,7 +84,7 @@ namespace voxels {
private: private:
const Level& level; const Level& level;
const GlobalChunks& chunks; const GlobalChunks& chunks;
const ContentUnitIndices<Block>& blockDefs; const ContentUnitIndices<Block, blockid_t>& blockDefs;
std::unordered_map<int, Agent> agents; std::unordered_map<int, Agent> agents;
int nextAgent = 1; int nextAgent = 1;

View file

@ -104,9 +104,9 @@ void WorldFiles::writePacks(const std::vector<ContentPack>& packs) {
io::write_string(packsFile, ss.str()); io::write_string(packsFile, ss.str());
} }
template <class T> template <class T, typename IdType>
static void write_indices( static void write_indices(
const ContentUnitIndices<T>& indices, dv::value& list const ContentUnitIndices<T, IdType>& indices, dv::value& list
) { ) {
for (auto unit : indices.getIterable()) { for (auto unit : indices.getIterable()) {
list.add(unit->name); list.add(unit->name);