move Chunks from Level to Player
This commit is contained in:
parent
b7664b4188
commit
1c18c02092
@ -5,11 +5,9 @@ test.reconfig_packs({"base"}, {})
|
|||||||
test.new_world("demo", "2019", "core:default")
|
test.new_world("demo", "2019", "core:default")
|
||||||
local pid = player.create("Xerxes")
|
local pid = player.create("Xerxes")
|
||||||
assert(player.get_name(pid) == "Xerxes")
|
assert(player.get_name(pid) == "Xerxes")
|
||||||
test.sleep_until(function() return world.count_chunks() >= 9 end, 1000)
|
test.sleep_until(function() return block.get(0, 0, 0) >= 0 end, 1000)
|
||||||
print(world.count_chunks())
|
print(world.count_chunks())
|
||||||
|
|
||||||
timeit(10000000, block.get, 0, 0, 0)
|
|
||||||
|
|
||||||
block.destruct(0, 0, 0, pid)
|
block.destruct(0, 0, 0, pid)
|
||||||
assert(block.get(0, 0, 0) == 0)
|
assert(block.get(0, 0, 0) == 0)
|
||||||
test.close_world(true)
|
test.close_world(true)
|
||||||
|
|||||||
@ -49,6 +49,8 @@ void TestMainloop::setLevel(std::unique_ptr<Level> level) {
|
|||||||
engine.getPaths()->setCurrentWorldFolder(fs::path());
|
engine.getPaths()->setCurrentWorldFolder(fs::path());
|
||||||
controller = nullptr;
|
controller = nullptr;
|
||||||
} else {
|
} else {
|
||||||
controller = std::make_unique<LevelController>(&engine, std::move(level));
|
controller = std::make_unique<LevelController>(
|
||||||
|
&engine, std::move(level), nullptr
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,7 +106,7 @@ std::shared_ptr<UINode> HudElement::getNode() const {
|
|||||||
std::shared_ptr<InventoryView> Hud::createContentAccess() {
|
std::shared_ptr<InventoryView> Hud::createContentAccess() {
|
||||||
auto content = frontend.getLevel().content;
|
auto content = frontend.getLevel().content;
|
||||||
auto indices = content->getIndices();
|
auto indices = content->getIndices();
|
||||||
auto inventory = player->getInventory();
|
auto inventory = player.getInventory();
|
||||||
|
|
||||||
size_t itemsCount = indices->items.count();
|
size_t itemsCount = indices->items.count();
|
||||||
auto accessInventory = std::make_shared<Inventory>(0, itemsCount);
|
auto accessInventory = std::make_shared<Inventory>(0, itemsCount);
|
||||||
@ -120,7 +120,7 @@ std::shared_ptr<InventoryView> Hud::createContentAccess() {
|
|||||||
inventory->move(copy, indices);
|
inventory->move(copy, indices);
|
||||||
},
|
},
|
||||||
[=](uint, ItemStack& item) {
|
[=](uint, ItemStack& item) {
|
||||||
inventory->getSlot(player->getChosenSlot()).set(item);
|
inventory->getSlot(player.getChosenSlot()).set(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
InventoryBuilder builder;
|
InventoryBuilder builder;
|
||||||
@ -132,7 +132,7 @@ std::shared_ptr<InventoryView> Hud::createContentAccess() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<InventoryView> Hud::createHotbar() {
|
std::shared_ptr<InventoryView> Hud::createHotbar() {
|
||||||
auto inventory = player->getInventory();
|
auto inventory = player.getInventory();
|
||||||
auto content = frontend.getLevel().content;
|
auto content = frontend.getLevel().content;
|
||||||
|
|
||||||
SlotLayout slotLayout(-1, glm::vec2(), false, false, nullptr, nullptr, nullptr);
|
SlotLayout slotLayout(-1, glm::vec2(), false, false, nullptr, nullptr, nullptr);
|
||||||
@ -148,7 +148,7 @@ std::shared_ptr<InventoryView> Hud::createHotbar() {
|
|||||||
|
|
||||||
static constexpr uint WORLDGEN_IMG_SIZE = 128U;
|
static constexpr uint WORLDGEN_IMG_SIZE = 128U;
|
||||||
|
|
||||||
Hud::Hud(Engine* engine, LevelFrontend& frontend, Player* player)
|
Hud::Hud(Engine* engine, LevelFrontend& frontend, Player& player)
|
||||||
: engine(engine),
|
: engine(engine),
|
||||||
assets(engine->getAssets()),
|
assets(engine->getAssets()),
|
||||||
gui(engine->getGUI()),
|
gui(engine->getGUI()),
|
||||||
@ -177,7 +177,7 @@ Hud::Hud(Engine* engine, LevelFrontend& frontend, Player* player)
|
|||||||
uicamera->flipped = true;
|
uicamera->flipped = true;
|
||||||
|
|
||||||
debugPanel = create_debug_panel(
|
debugPanel = create_debug_panel(
|
||||||
engine, frontend.getLevel(), *player, allowDebugCheats
|
engine, frontend.getLevel(), player, allowDebugCheats
|
||||||
);
|
);
|
||||||
debugPanel->setZIndex(2);
|
debugPanel->setZIndex(2);
|
||||||
gui->add(debugPanel);
|
gui->add(debugPanel);
|
||||||
@ -246,12 +246,12 @@ void Hud::processInput(bool visible) {
|
|||||||
|
|
||||||
void Hud::updateHotbarControl() {
|
void Hud::updateHotbarControl() {
|
||||||
if (!inventoryOpen && Events::scroll) {
|
if (!inventoryOpen && Events::scroll) {
|
||||||
int slot = player->getChosenSlot();
|
int slot = player.getChosenSlot();
|
||||||
slot = (slot - Events::scroll) % 10;
|
slot = (slot - Events::scroll) % 10;
|
||||||
if (slot < 0) {
|
if (slot < 0) {
|
||||||
slot += 10;
|
slot += 10;
|
||||||
}
|
}
|
||||||
player->setChosenSlot(slot);
|
player.setChosenSlot(slot);
|
||||||
}
|
}
|
||||||
for (
|
for (
|
||||||
int i = static_cast<int>(keycode::NUM_1);
|
int i = static_cast<int>(keycode::NUM_1);
|
||||||
@ -259,17 +259,17 @@ void Hud::updateHotbarControl() {
|
|||||||
i++
|
i++
|
||||||
) {
|
) {
|
||||||
if (Events::jpressed(i)) {
|
if (Events::jpressed(i)) {
|
||||||
player->setChosenSlot(i - static_cast<int>(keycode::NUM_1));
|
player.setChosenSlot(i - static_cast<int>(keycode::NUM_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Events::jpressed(keycode::NUM_0)) {
|
if (Events::jpressed(keycode::NUM_0)) {
|
||||||
player->setChosenSlot(9);
|
player.setChosenSlot(9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hud::updateWorldGenDebugVisualization() {
|
void Hud::updateWorldGenDebugVisualization() {
|
||||||
auto& level = frontend.getLevel();
|
auto& level = frontend.getLevel();
|
||||||
auto& chunks = *level.chunks;
|
const auto& chunks = *player.chunks;
|
||||||
auto generator =
|
auto generator =
|
||||||
frontend.getController()->getChunksController()->getGenerator();
|
frontend.getController()->getChunksController()->getGenerator();
|
||||||
auto debugInfo = generator->createDebugInfo();
|
auto debugInfo = generator->createDebugInfo();
|
||||||
@ -318,9 +318,10 @@ void Hud::updateWorldGenDebugVisualization() {
|
|||||||
|
|
||||||
void Hud::update(bool visible) {
|
void Hud::update(bool visible) {
|
||||||
const auto& level = frontend.getLevel();
|
const auto& level = frontend.getLevel();
|
||||||
|
const auto& chunks = *player.chunks;
|
||||||
auto menu = gui->getMenu();
|
auto menu = gui->getMenu();
|
||||||
|
|
||||||
debugPanel->setVisible(player->debug && visible);
|
debugPanel->setVisible(player.debug && visible);
|
||||||
|
|
||||||
if (!visible && inventoryOpen) {
|
if (!visible && inventoryOpen) {
|
||||||
closeInventory();
|
closeInventory();
|
||||||
@ -337,7 +338,7 @@ void Hud::update(bool visible) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (blockUI) {
|
if (blockUI) {
|
||||||
voxel* vox = level.chunks->get(blockPos.x, blockPos.y, blockPos.z);
|
voxel* vox = chunks.get(blockPos.x, blockPos.y, blockPos.z);
|
||||||
if (vox == nullptr || vox->id != currentblockid) {
|
if (vox == nullptr || vox->id != currentblockid) {
|
||||||
closeInventory();
|
closeInventory();
|
||||||
}
|
}
|
||||||
@ -355,7 +356,7 @@ void Hud::update(bool visible) {
|
|||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
for (auto& element : elements) {
|
for (auto& element : elements) {
|
||||||
element.update(pause, inventoryOpen, player->debug);
|
element.update(pause, inventoryOpen, player.debug);
|
||||||
if (element.isRemoved()) {
|
if (element.isRemoved()) {
|
||||||
onRemove(element);
|
onRemove(element);
|
||||||
}
|
}
|
||||||
@ -363,8 +364,8 @@ void Hud::update(bool visible) {
|
|||||||
}
|
}
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
debugMinimap->setVisible(player->debug && showGeneratorMinimap);
|
debugMinimap->setVisible(player.debug && showGeneratorMinimap);
|
||||||
if (player->debug && showGeneratorMinimap) {
|
if (player.debug && showGeneratorMinimap) {
|
||||||
updateWorldGenDebugVisualization();
|
updateWorldGenDebugVisualization();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,7 +376,7 @@ void Hud::openInventory() {
|
|||||||
showExchangeSlot();
|
showExchangeSlot();
|
||||||
|
|
||||||
inventoryOpen = true;
|
inventoryOpen = true;
|
||||||
auto inventory = player->getInventory();
|
auto inventory = player.getInventory();
|
||||||
auto inventoryDocument = assets->get<UiDocument>("core:inventory");
|
auto inventoryDocument = assets->get<UiDocument>("core:inventory");
|
||||||
inventoryView = std::dynamic_pointer_cast<InventoryView>(inventoryDocument->getRoot());
|
inventoryView = std::dynamic_pointer_cast<InventoryView>(inventoryDocument->getRoot());
|
||||||
inventoryView->bind(inventory, content);
|
inventoryView->bind(inventory, content);
|
||||||
@ -422,7 +423,9 @@ void Hud::openInventory(
|
|||||||
closeInventory();
|
closeInventory();
|
||||||
}
|
}
|
||||||
auto& level = frontend.getLevel();
|
auto& level = frontend.getLevel();
|
||||||
|
const auto& chunks = *player.chunks;
|
||||||
auto content = level.content;
|
auto content = level.content;
|
||||||
|
|
||||||
blockUI = std::dynamic_pointer_cast<InventoryView>(doc->getRoot());
|
blockUI = std::dynamic_pointer_cast<InventoryView>(doc->getRoot());
|
||||||
if (blockUI == nullptr) {
|
if (blockUI == nullptr) {
|
||||||
throw std::runtime_error("block UI root element must be 'inventory'");
|
throw std::runtime_error("block UI root element must be 'inventory'");
|
||||||
@ -436,10 +439,10 @@ void Hud::openInventory(
|
|||||||
if (blockinv == nullptr) {
|
if (blockinv == nullptr) {
|
||||||
blockinv = level.inventories->createVirtual(blockUI->getSlotsCount());
|
blockinv = level.inventories->createVirtual(blockUI->getSlotsCount());
|
||||||
}
|
}
|
||||||
level.chunks->getChunkByVoxel(block.x, block.y, block.z)->flags.unsaved = true;
|
chunks.getChunkByVoxel(block.x, block.y, block.z)->flags.unsaved = true;
|
||||||
blockUI->bind(blockinv, content);
|
blockUI->bind(blockinv, content);
|
||||||
blockPos = block;
|
blockPos = block;
|
||||||
currentblockid = level.chunks->get(block.x, block.y, block.z)->id;
|
currentblockid = chunks.require(block.x, block.y, block.z).id;
|
||||||
add(HudElement(hud_element_mode::inventory_bound, doc, blockUI, false));
|
add(HudElement(hud_element_mode::inventory_bound, doc, blockUI, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,7 +484,7 @@ void Hud::openPermanent(UiDocument* doc) {
|
|||||||
|
|
||||||
auto invview = std::dynamic_pointer_cast<InventoryView>(root);
|
auto invview = std::dynamic_pointer_cast<InventoryView>(root);
|
||||||
if (invview) {
|
if (invview) {
|
||||||
invview->bind(player->getInventory(), frontend.getLevel().content);
|
invview->bind(player.getInventory(), frontend.getLevel().content);
|
||||||
}
|
}
|
||||||
add(HudElement(hud_element_mode::permanent, doc, doc->getRoot(), false));
|
add(HudElement(hud_element_mode::permanent, doc, doc->getRoot(), false));
|
||||||
}
|
}
|
||||||
@ -571,7 +574,7 @@ void Hud::draw(const DrawContext& ctx){
|
|||||||
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||||
|
|
||||||
// Crosshair
|
// Crosshair
|
||||||
if (!pause && !inventoryOpen && !player->debug) {
|
if (!pause && !inventoryOpen && !player.debug) {
|
||||||
DrawContext chctx = ctx.sub(batch);
|
DrawContext chctx = ctx.sub(batch);
|
||||||
chctx.setBlendMode(BlendMode::inversion);
|
chctx.setBlendMode(BlendMode::inversion);
|
||||||
auto texture = assets->get<Texture>("gui/crosshair");
|
auto texture = assets->get<Texture>("gui/crosshair");
|
||||||
@ -629,7 +632,7 @@ void Hud::updateElementsPosition(const Viewport& viewport) {
|
|||||||
exchangeSlot->setPos(glm::vec2(Events::cursor));
|
exchangeSlot->setPos(glm::vec2(Events::cursor));
|
||||||
}
|
}
|
||||||
hotbarView->setPos(glm::vec2(width/2, height-65));
|
hotbarView->setPos(glm::vec2(width/2, height-65));
|
||||||
hotbarView->setSelected(player->getChosenSlot());
|
hotbarView->setSelected(player.getChosenSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hud::isInventoryOpen() const {
|
bool Hud::isInventoryOpen() const {
|
||||||
@ -661,7 +664,7 @@ void Hud::setPause(bool pause) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Player* Hud::getPlayer() const {
|
Player* Hud::getPlayer() const {
|
||||||
return player;
|
return &player;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Inventory> Hud::getBlockInventory() {
|
std::shared_ptr<Inventory> Hud::getBlockInventory() {
|
||||||
@ -684,7 +687,7 @@ void Hud::setDebugCheats(bool flag) {
|
|||||||
|
|
||||||
gui->remove(debugPanel);
|
gui->remove(debugPanel);
|
||||||
debugPanel = create_debug_panel(
|
debugPanel = create_debug_panel(
|
||||||
engine, frontend.getLevel(), *player, allowDebugCheats
|
engine, frontend.getLevel(), player, allowDebugCheats
|
||||||
);
|
);
|
||||||
debugPanel->setZIndex(2);
|
debugPanel->setZIndex(2);
|
||||||
gui->add(debugPanel);
|
gui->add(debugPanel);
|
||||||
|
|||||||
@ -75,7 +75,7 @@ class Hud : public util::ObjectsKeeper {
|
|||||||
std::unique_ptr<Camera> uicamera;
|
std::unique_ptr<Camera> uicamera;
|
||||||
gui::GUI* gui;
|
gui::GUI* gui;
|
||||||
LevelFrontend& frontend;
|
LevelFrontend& frontend;
|
||||||
Player* player;
|
Player& player;
|
||||||
|
|
||||||
/// @brief Is any overlay/inventory open
|
/// @brief Is any overlay/inventory open
|
||||||
bool inventoryOpen = false;
|
bool inventoryOpen = false;
|
||||||
@ -131,7 +131,7 @@ class Hud : public util::ObjectsKeeper {
|
|||||||
void showExchangeSlot();
|
void showExchangeSlot();
|
||||||
void updateWorldGenDebugVisualization();
|
void updateWorldGenDebugVisualization();
|
||||||
public:
|
public:
|
||||||
Hud(Engine* engine, LevelFrontend& frontend, Player* player);
|
Hud(Engine* engine, LevelFrontend& frontend, Player& player);
|
||||||
~Hud();
|
~Hud();
|
||||||
|
|
||||||
void update(bool hudVisible);
|
void update(bool hudVisible);
|
||||||
|
|||||||
@ -44,9 +44,9 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> levelPtr)
|
|||||||
auto menu = engine->getGUI()->getMenu();
|
auto menu = engine->getGUI()->getMenu();
|
||||||
menu->reset();
|
menu->reset();
|
||||||
|
|
||||||
controller = std::make_unique<LevelController>(engine, std::move(levelPtr));
|
|
||||||
|
|
||||||
auto player = level->players->get(0);
|
auto player = level->players->get(0);
|
||||||
|
controller =
|
||||||
|
std::make_unique<LevelController>(engine, std::move(levelPtr), player);
|
||||||
playerController = std::make_unique<PlayerController>(
|
playerController = std::make_unique<PlayerController>(
|
||||||
settings,
|
settings,
|
||||||
level,
|
level,
|
||||||
@ -60,21 +60,21 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> levelPtr)
|
|||||||
worldRenderer = std::make_unique<WorldRenderer>(
|
worldRenderer = std::make_unique<WorldRenderer>(
|
||||||
engine, *frontend, player
|
engine, *frontend, player
|
||||||
);
|
);
|
||||||
hud = std::make_unique<Hud>(engine, *frontend, player);
|
hud = std::make_unique<Hud>(engine, *frontend, *player);
|
||||||
|
|
||||||
decorator = std::make_unique<Decorator>(
|
decorator = std::make_unique<Decorator>(
|
||||||
*engine, *controller, *worldRenderer, assets, *player
|
*engine, *controller, *worldRenderer, assets, *player
|
||||||
);
|
);
|
||||||
|
|
||||||
keepAlive(settings.graphics.backlight.observe([=](bool) {
|
keepAlive(settings.graphics.backlight.observe([=](bool) {
|
||||||
controller->getLevel()->chunks->saveAndClear();
|
player->chunks->saveAndClear();
|
||||||
worldRenderer->clear();
|
worldRenderer->clear();
|
||||||
}));
|
}));
|
||||||
keepAlive(settings.camera.fov.observe([=](double value) {
|
keepAlive(settings.camera.fov.observe([=](double value) {
|
||||||
player->fpCamera->setFov(glm::radians(value));
|
player->fpCamera->setFov(glm::radians(value));
|
||||||
}));
|
}));
|
||||||
keepAlive(Events::getBinding(BIND_CHUNKS_RELOAD).onactived.add([=](){
|
keepAlive(Events::getBinding(BIND_CHUNKS_RELOAD).onactived.add([=](){
|
||||||
controller->getLevel()->chunks->saveAndClear();
|
player->chunks->saveAndClear();
|
||||||
worldRenderer->clear();
|
worldRenderer->clear();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@ -14,15 +14,18 @@
|
|||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
|
|
||||||
BlockWrapsRenderer::BlockWrapsRenderer(const Assets& assets, const Level& level)
|
BlockWrapsRenderer::BlockWrapsRenderer(
|
||||||
: assets(assets), level(level), batch(std::make_unique<MainBatch>(1024)) {
|
const Assets& assets, const Level& level, const Chunks& chunks
|
||||||
|
)
|
||||||
|
: assets(assets),
|
||||||
|
level(level),
|
||||||
|
chunks(chunks),
|
||||||
|
batch(std::make_unique<MainBatch>(1024)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockWrapsRenderer::~BlockWrapsRenderer() = default;
|
BlockWrapsRenderer::~BlockWrapsRenderer() = default;
|
||||||
|
|
||||||
void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
||||||
const auto& chunks = *level.chunks;
|
|
||||||
|
|
||||||
auto textureRegion = util::get_texture_region(assets, wrapper.texture, "");
|
auto textureRegion = util::get_texture_region(assets, wrapper.texture, "");
|
||||||
|
|
||||||
auto& shader = assets.require<Shader>("entity");
|
auto& shader = assets.require<Shader>("entity");
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
class Assets;
|
class Assets;
|
||||||
class Player;
|
class Player;
|
||||||
class Level;
|
class Level;
|
||||||
|
class Chunks;
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
|
|
||||||
struct BlockWrapper {
|
struct BlockWrapper {
|
||||||
@ -20,6 +21,7 @@ struct BlockWrapper {
|
|||||||
class BlockWrapsRenderer {
|
class BlockWrapsRenderer {
|
||||||
const Assets& assets;
|
const Assets& assets;
|
||||||
const Level& level;
|
const Level& level;
|
||||||
|
const Chunks& chunks;
|
||||||
std::unique_ptr<MainBatch> batch;
|
std::unique_ptr<MainBatch> batch;
|
||||||
|
|
||||||
std::unordered_map<u64id_t, std::unique_ptr<BlockWrapper>> wrappers;
|
std::unordered_map<u64id_t, std::unique_ptr<BlockWrapper>> wrappers;
|
||||||
@ -27,7 +29,9 @@ class BlockWrapsRenderer {
|
|||||||
|
|
||||||
void draw(const BlockWrapper& wrapper);
|
void draw(const BlockWrapper& wrapper);
|
||||||
public:
|
public:
|
||||||
BlockWrapsRenderer(const Assets& assets, const Level& level);
|
BlockWrapsRenderer(
|
||||||
|
const Assets& assets, const Level& level, const Chunks& chunks
|
||||||
|
);
|
||||||
~BlockWrapsRenderer();
|
~BlockWrapsRenderer();
|
||||||
|
|
||||||
void draw(const DrawContext& ctx, const Player& player);
|
void draw(const DrawContext& ctx, const Player& player);
|
||||||
|
|||||||
@ -20,19 +20,22 @@ size_t ChunksRenderer::visibleChunks = 0;
|
|||||||
|
|
||||||
class RendererWorker : public util::Worker<std::shared_ptr<Chunk>, RendererResult> {
|
class RendererWorker : public util::Worker<std::shared_ptr<Chunk>, RendererResult> {
|
||||||
const Level& level;
|
const Level& level;
|
||||||
|
const Chunks& chunks;
|
||||||
BlocksRenderer renderer;
|
BlocksRenderer renderer;
|
||||||
public:
|
public:
|
||||||
RendererWorker(
|
RendererWorker(
|
||||||
const Level& level,
|
const Level& level,
|
||||||
|
const Chunks& chunks,
|
||||||
const ContentGfxCache& cache,
|
const ContentGfxCache& cache,
|
||||||
const EngineSettings& settings
|
const EngineSettings& settings
|
||||||
) : level(level),
|
) : level(level),
|
||||||
|
chunks(chunks),
|
||||||
renderer(settings.graphics.chunkMaxVertices.get(),
|
renderer(settings.graphics.chunkMaxVertices.get(),
|
||||||
*level.content, cache, settings)
|
*level.content, cache, settings)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
RendererResult operator()(const std::shared_ptr<Chunk>& chunk) override {
|
RendererResult operator()(const std::shared_ptr<Chunk>& chunk) override {
|
||||||
renderer.build(chunk.get(), level.chunks.get());
|
renderer.build(chunk.get(), &chunks);
|
||||||
if (renderer.isCancelled()) {
|
if (renderer.isCancelled()) {
|
||||||
return RendererResult {
|
return RendererResult {
|
||||||
glm::ivec2(chunk->x, chunk->z), true, MeshData()};
|
glm::ivec2(chunk->x, chunk->z), true, MeshData()};
|
||||||
@ -45,28 +48,35 @@ public:
|
|||||||
|
|
||||||
ChunksRenderer::ChunksRenderer(
|
ChunksRenderer::ChunksRenderer(
|
||||||
const Level* level,
|
const Level* level,
|
||||||
|
const Chunks& chunks,
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
const Frustum& frustum,
|
const Frustum& frustum,
|
||||||
const ContentGfxCache& cache,
|
const ContentGfxCache& cache,
|
||||||
const EngineSettings& settings
|
const EngineSettings& settings
|
||||||
) : level(*level),
|
)
|
||||||
|
: level(*level),
|
||||||
|
chunks(chunks),
|
||||||
assets(assets),
|
assets(assets),
|
||||||
frustum(frustum),
|
frustum(frustum),
|
||||||
settings(settings),
|
settings(settings),
|
||||||
threadPool(
|
threadPool(
|
||||||
"chunks-render-pool",
|
"chunks-render-pool",
|
||||||
[&](){return std::make_shared<RendererWorker>(*level, cache, settings);},
|
[&]() {
|
||||||
[&](RendererResult& result){
|
return std::make_shared<RendererWorker>(
|
||||||
|
*level, chunks, cache, settings
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[&](RendererResult& result) {
|
||||||
if (!result.cancelled) {
|
if (!result.cancelled) {
|
||||||
auto meshData = std::move(result.meshData);
|
auto meshData = std::move(result.meshData);
|
||||||
meshes[result.key] = ChunkMesh {
|
meshes[result.key] = ChunkMesh {
|
||||||
std::make_unique<Mesh>(meshData.mesh),
|
std::make_unique<Mesh>(meshData.mesh),
|
||||||
std::move(meshData.sortingMesh)
|
std::move(meshData.sortingMesh)};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
inwork.erase(result.key);
|
inwork.erase(result.key);
|
||||||
}, settings.graphics.chunkMaxRenderers.get())
|
},
|
||||||
{
|
settings.graphics.chunkMaxRenderers.get()
|
||||||
|
) {
|
||||||
threadPool.setStopOnFail(false);
|
threadPool.setStopOnFail(false);
|
||||||
renderer = std::make_unique<BlocksRenderer>(
|
renderer = std::make_unique<BlocksRenderer>(
|
||||||
settings.graphics.chunkMaxVertices.get(),
|
settings.graphics.chunkMaxVertices.get(),
|
||||||
@ -83,7 +93,7 @@ const Mesh* ChunksRenderer::render(
|
|||||||
) {
|
) {
|
||||||
chunk->flags.modified = false;
|
chunk->flags.modified = false;
|
||||||
if (important) {
|
if (important) {
|
||||||
auto mesh = renderer->render(chunk.get(), level.chunks.get());
|
auto mesh = renderer->render(chunk.get(), &chunks);
|
||||||
meshes[glm::ivec2(chunk->x, chunk->z)] = ChunkMesh {
|
meshes[glm::ivec2(chunk->x, chunk->z)] = ChunkMesh {
|
||||||
std::move(mesh.mesh), std::move(mesh.sortingMeshData)
|
std::move(mesh.mesh), std::move(mesh.sortingMeshData)
|
||||||
};
|
};
|
||||||
@ -131,7 +141,7 @@ void ChunksRenderer::update() {
|
|||||||
const Mesh* ChunksRenderer::retrieveChunk(
|
const Mesh* ChunksRenderer::retrieveChunk(
|
||||||
size_t index, const Camera& camera, Shader& shader, bool culling
|
size_t index, const Camera& camera, Shader& shader, bool culling
|
||||||
) {
|
) {
|
||||||
auto chunk = level.chunks->getChunks()[index];
|
auto chunk = chunks.getChunks()[index];
|
||||||
if (chunk == nullptr || !chunk->flags.lighted) {
|
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -163,7 +173,6 @@ const Mesh* ChunksRenderer::retrieveChunk(
|
|||||||
void ChunksRenderer::drawChunks(
|
void ChunksRenderer::drawChunks(
|
||||||
const Camera& camera, Shader& shader
|
const Camera& camera, Shader& shader
|
||||||
) {
|
) {
|
||||||
const auto& chunks = *level.chunks;
|
|
||||||
const auto& atlas = assets.require<Atlas>("blocks");
|
const auto& atlas = assets.require<Atlas>("blocks");
|
||||||
|
|
||||||
atlas.getTexture()->bind();
|
atlas.getTexture()->bind();
|
||||||
@ -232,7 +241,7 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) {
|
|||||||
frameid++;
|
frameid++;
|
||||||
|
|
||||||
bool culling = settings.graphics.frustumCulling.get();
|
bool culling = settings.graphics.frustumCulling.get();
|
||||||
const auto& chunks = level.chunks->getChunks();
|
const auto& chunks = this->chunks.getChunks();
|
||||||
const auto& cameraPos = camera.position;
|
const auto& cameraPos = camera.position;
|
||||||
const auto& atlas = assets.require<Atlas>("blocks");
|
const auto& atlas = assets.require<Atlas>("blocks");
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class Level;
|
|||||||
class Camera;
|
class Camera;
|
||||||
class Shader;
|
class Shader;
|
||||||
class Assets;
|
class Assets;
|
||||||
|
class Chunks;
|
||||||
class Frustum;
|
class Frustum;
|
||||||
class BlocksRenderer;
|
class BlocksRenderer;
|
||||||
class ContentGfxCache;
|
class ContentGfxCache;
|
||||||
@ -42,6 +43,7 @@ struct RendererResult {
|
|||||||
|
|
||||||
class ChunksRenderer {
|
class ChunksRenderer {
|
||||||
const Level& level;
|
const Level& level;
|
||||||
|
const Chunks& chunks;
|
||||||
const Assets& assets;
|
const Assets& assets;
|
||||||
const Frustum& frustum;
|
const Frustum& frustum;
|
||||||
const EngineSettings& settings;
|
const EngineSettings& settings;
|
||||||
@ -57,6 +59,7 @@ class ChunksRenderer {
|
|||||||
public:
|
public:
|
||||||
ChunksRenderer(
|
ChunksRenderer(
|
||||||
const Level* level,
|
const Level* level,
|
||||||
|
const Chunks& chunks,
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
const Frustum& frustum,
|
const Frustum& frustum,
|
||||||
const ContentGfxCache& cache,
|
const ContentGfxCache& cache,
|
||||||
|
|||||||
@ -85,7 +85,7 @@ void Decorator::update(
|
|||||||
int index = currentIndex;
|
int index = currentIndex;
|
||||||
currentIndex = (currentIndex + BIG_PRIME) % UPDATE_BLOCKS;
|
currentIndex = (currentIndex + BIG_PRIME) % UPDATE_BLOCKS;
|
||||||
|
|
||||||
const auto& chunks = *level.chunks;
|
const auto& chunks = *player.chunks;
|
||||||
const auto& indices = *level.content->getIndices();
|
const auto& indices = *level.content->getIndices();
|
||||||
|
|
||||||
int lx = index % UPDATE_AREA_DIAMETER;
|
int lx = index % UPDATE_AREA_DIAMETER;
|
||||||
@ -108,7 +108,7 @@ void Decorator::update(float delta, const Camera& camera) {
|
|||||||
for (int i = 0; i < ITERATIONS; i++) {
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
update(delta, pos, camera.position);
|
update(delta, pos, camera.position);
|
||||||
}
|
}
|
||||||
const auto& chunks = *level.chunks;
|
const auto& chunks = *player.chunks;
|
||||||
const auto& indices = *level.content->getIndices();
|
const auto& indices = *level.content->getIndices();
|
||||||
auto iter = blockEmitters.begin();
|
auto iter = blockEmitters.begin();
|
||||||
while (iter != blockEmitters.end()) {
|
while (iter != blockEmitters.end()) {
|
||||||
|
|||||||
@ -16,12 +16,17 @@ size_t ParticlesRenderer::visibleParticles = 0;
|
|||||||
size_t ParticlesRenderer::aliveEmitters = 0;
|
size_t ParticlesRenderer::aliveEmitters = 0;
|
||||||
|
|
||||||
ParticlesRenderer::ParticlesRenderer(
|
ParticlesRenderer::ParticlesRenderer(
|
||||||
const Assets& assets, const Level& level, const GraphicsSettings* settings
|
const Assets& assets,
|
||||||
|
const Level& level,
|
||||||
|
const Chunks& chunks,
|
||||||
|
const GraphicsSettings* settings
|
||||||
)
|
)
|
||||||
: batch(std::make_unique<MainBatch>(4096)),
|
: batch(std::make_unique<MainBatch>(4096)),
|
||||||
level(level),
|
level(level),
|
||||||
|
chunks(chunks),
|
||||||
assets(assets),
|
assets(assets),
|
||||||
settings(settings) {}
|
settings(settings) {
|
||||||
|
}
|
||||||
|
|
||||||
ParticlesRenderer::~ParticlesRenderer() = default;
|
ParticlesRenderer::~ParticlesRenderer() = default;
|
||||||
|
|
||||||
@ -44,7 +49,6 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
|
|||||||
const auto& right = camera.right;
|
const auto& right = camera.right;
|
||||||
const auto& up = camera.up;
|
const auto& up = camera.up;
|
||||||
|
|
||||||
const auto& chunks = *level.chunks;
|
|
||||||
bool backlight = settings->backlight.get();
|
bool backlight = settings->backlight.get();
|
||||||
|
|
||||||
std::vector<const Texture*> unusedTextures;
|
std::vector<const Texture*> unusedTextures;
|
||||||
|
|||||||
@ -10,12 +10,14 @@
|
|||||||
class Texture;
|
class Texture;
|
||||||
class Assets;
|
class Assets;
|
||||||
class Camera;
|
class Camera;
|
||||||
|
class Chunks;
|
||||||
class MainBatch;
|
class MainBatch;
|
||||||
class Level;
|
class Level;
|
||||||
struct GraphicsSettings;
|
struct GraphicsSettings;
|
||||||
|
|
||||||
class ParticlesRenderer {
|
class ParticlesRenderer {
|
||||||
const Level& level;
|
const Level& level;
|
||||||
|
const Chunks& chunks;
|
||||||
const Assets& assets;
|
const Assets& assets;
|
||||||
const GraphicsSettings* settings;
|
const GraphicsSettings* settings;
|
||||||
std::unordered_map<const Texture*, std::vector<Particle>> particles;
|
std::unordered_map<const Texture*, std::vector<Particle>> particles;
|
||||||
@ -29,6 +31,7 @@ public:
|
|||||||
ParticlesRenderer(
|
ParticlesRenderer(
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
const Level& level,
|
const Level& level,
|
||||||
|
const Chunks& chunks,
|
||||||
const GraphicsSettings* settings
|
const GraphicsSettings* settings
|
||||||
);
|
);
|
||||||
~ParticlesRenderer();
|
~ParticlesRenderer();
|
||||||
|
|||||||
@ -68,21 +68,24 @@ WorldRenderer::WorldRenderer(
|
|||||||
lineBatch(std::make_unique<LineBatch>()),
|
lineBatch(std::make_unique<LineBatch>()),
|
||||||
batch3d(std::make_unique<Batch3D>(BATCH3D_CAPACITY)),
|
batch3d(std::make_unique<Batch3D>(BATCH3D_CAPACITY)),
|
||||||
modelBatch(std::make_unique<ModelBatch>(
|
modelBatch(std::make_unique<ModelBatch>(
|
||||||
MODEL_BATCH_CAPACITY, assets, *level.chunks, engine->getSettings()
|
MODEL_BATCH_CAPACITY, assets, *player->chunks, engine->getSettings()
|
||||||
)),
|
)),
|
||||||
particles(std::make_unique<ParticlesRenderer>(
|
particles(std::make_unique<ParticlesRenderer>(
|
||||||
assets, level, &engine->getSettings().graphics
|
assets, level, *player->chunks, &engine->getSettings().graphics
|
||||||
)),
|
)),
|
||||||
texts(std::make_unique<TextsRenderer>(*batch3d, assets, *frustumCulling)),
|
texts(std::make_unique<TextsRenderer>(*batch3d, assets, *frustumCulling)),
|
||||||
guides(std::make_unique<GuidesRenderer>()),
|
guides(std::make_unique<GuidesRenderer>()),
|
||||||
chunks(std::make_unique<ChunksRenderer>(
|
chunks(std::make_unique<ChunksRenderer>(
|
||||||
&level,
|
&level,
|
||||||
|
*player->chunks,
|
||||||
assets,
|
assets,
|
||||||
*frustumCulling,
|
*frustumCulling,
|
||||||
frontend.getContentGfxCache(),
|
frontend.getContentGfxCache(),
|
||||||
engine->getSettings()
|
engine->getSettings()
|
||||||
)),
|
)),
|
||||||
blockWraps(std::make_unique<BlockWrapsRenderer>(assets, level)) {
|
blockWraps(
|
||||||
|
std::make_unique<BlockWrapsRenderer>(assets, level, *player->chunks)
|
||||||
|
) {
|
||||||
auto& settings = engine->getSettings();
|
auto& settings = engine->getSettings();
|
||||||
level.events->listen(
|
level.events->listen(
|
||||||
EVT_CHUNK_HIDDEN,
|
EVT_CHUNK_HIDDEN,
|
||||||
@ -362,7 +365,7 @@ void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) {
|
|||||||
int x = std::floor(player->currentCamera->position.x);
|
int x = std::floor(player->currentCamera->position.x);
|
||||||
int y = std::floor(player->currentCamera->position.y);
|
int y = std::floor(player->currentCamera->position.y);
|
||||||
int z = std::floor(player->currentCamera->position.z);
|
int z = std::floor(player->currentCamera->position.z);
|
||||||
auto block = level.chunks->get(x, y, z);
|
auto block = player->chunks->get(x, y, z);
|
||||||
if (block && block->id) {
|
if (block && block->id) {
|
||||||
const auto& def =
|
const auto& def =
|
||||||
level.content->getIndices()->blocks.require(block->id);
|
level.content->getIndices()->blocks.require(block->id);
|
||||||
@ -381,7 +384,7 @@ void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) {
|
|||||||
batch3d->begin();
|
batch3d->begin();
|
||||||
shader.uniformMatrix("u_projview", glm::mat4(1.0f));
|
shader.uniformMatrix("u_projview", glm::mat4(1.0f));
|
||||||
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
||||||
auto light = level.chunks->getLight(x, y, z);
|
auto light = player->chunks->getLight(x, y, z);
|
||||||
float s = Lightmap::extract(light, 3) / 15.0f;
|
float s = Lightmap::extract(light, 3) / 15.0f;
|
||||||
glm::vec4 tint(
|
glm::vec4 tint(
|
||||||
glm::min(1.0f, Lightmap::extract(light, 0) / 15.0f + s),
|
glm::min(1.0f, Lightmap::extract(light, 0) / 15.0f + s),
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#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"
|
||||||
@ -11,12 +13,15 @@
|
|||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "voxels/voxel.hpp"
|
#include "voxels/voxel.hpp"
|
||||||
|
#include "voxels/blocks_agent.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "world/World.hpp"
|
#include "world/World.hpp"
|
||||||
|
#include "objects/Player.hpp"
|
||||||
|
#include "objects/Players.hpp"
|
||||||
|
|
||||||
BlocksController::BlocksController(const Level& level, Lighting& lighting, uint padding)
|
BlocksController::BlocksController(const Level& level, Lighting* lighting, uint padding)
|
||||||
: level(level),
|
: level(level),
|
||||||
chunks(*level.chunks),
|
chunks(*level.chunksStorage),
|
||||||
lighting(lighting),
|
lighting(lighting),
|
||||||
randTickClock(20, 3),
|
randTickClock(20, 3),
|
||||||
blocksTickClock(20, 1),
|
blocksTickClock(20, 1),
|
||||||
@ -34,7 +39,7 @@ void BlocksController::updateSides(int x, int y, int z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BlocksController::updateSides(int x, int y, int z, int w, int h, int d) {
|
void BlocksController::updateSides(int x, int y, int z, int w, int h, int d) {
|
||||||
voxel* vox = chunks.get(x, y, z);
|
voxel* vox = blocks_agent::get(chunks, x, y, z);
|
||||||
const auto& def = level.content->getIndices()->blocks.require(vox->id);
|
const auto& def = level.content->getIndices()->blocks.require(vox->id);
|
||||||
const auto& rot = def.rotations.variants[vox->state.rotation];
|
const auto& rot = def.rotations.variants[vox->state.rotation];
|
||||||
const auto& xaxis = rot.axisX;
|
const auto& xaxis = rot.axisX;
|
||||||
@ -62,8 +67,10 @@ void BlocksController::breakBlock(
|
|||||||
onBlockInteraction(
|
onBlockInteraction(
|
||||||
player, glm::ivec3(x, y, z), def, BlockInteraction::destruction
|
player, glm::ivec3(x, y, z), def, BlockInteraction::destruction
|
||||||
);
|
);
|
||||||
chunks.set(x, y, z, 0, {});
|
blocks_agent::set(chunks, x, y, z, 0, {});
|
||||||
lighting.onBlockSet(x, y, z, 0);
|
if (lighting) {
|
||||||
|
lighting->onBlockSet(x, y, z, 0);
|
||||||
|
}
|
||||||
scripting::on_block_broken(player, def, glm::ivec3(x, y, z));
|
scripting::on_block_broken(player, def, glm::ivec3(x, y, z));
|
||||||
if (def.rt.extended) {
|
if (def.rt.extended) {
|
||||||
updateSides(x, y, z , def.size.x, def.size.y, def.size.z);
|
updateSides(x, y, z , def.size.x, def.size.y, def.size.z);
|
||||||
@ -75,7 +82,7 @@ void BlocksController::breakBlock(
|
|||||||
void BlocksController::placeBlock(
|
void BlocksController::placeBlock(
|
||||||
Player* player, const Block& def, blockstate state, int x, int y, int z
|
Player* player, const Block& def, blockstate state, int x, int y, int z
|
||||||
) {
|
) {
|
||||||
auto voxel = chunks.get(x, y, z);
|
auto voxel = blocks_agent::get(chunks, x, y, z);
|
||||||
if (voxel == nullptr) {
|
if (voxel == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -85,8 +92,10 @@ void BlocksController::placeBlock(
|
|||||||
onBlockInteraction(
|
onBlockInteraction(
|
||||||
player, glm::ivec3(x, y, z), def, BlockInteraction::placing
|
player, glm::ivec3(x, y, z), def, BlockInteraction::placing
|
||||||
);
|
);
|
||||||
chunks.set(x, y, z, def.rt.id, state);
|
blocks_agent::set(chunks, x, y, z, def.rt.id, state);
|
||||||
lighting.onBlockSet(x, y, z, def.rt.id);
|
if (lighting) {
|
||||||
|
lighting->onBlockSet(x, y, z, def.rt.id);
|
||||||
|
}
|
||||||
scripting::on_block_placed(player, def, glm::ivec3(x, y, z));
|
scripting::on_block_placed(player, def, glm::ivec3(x, y, z));
|
||||||
if (def.rt.extended) {
|
if (def.rt.extended) {
|
||||||
updateSides(x, y, z , def.size.x, def.size.y, def.size.z);
|
updateSides(x, y, z , def.size.x, def.size.y, def.size.z);
|
||||||
@ -96,12 +105,12 @@ void BlocksController::placeBlock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BlocksController::updateBlock(int x, int y, int z) {
|
void BlocksController::updateBlock(int x, int y, int z) {
|
||||||
voxel* vox = chunks.get(x, y, z);
|
voxel* vox = blocks_agent::get(chunks, x, y, z);
|
||||||
if (vox == nullptr) return;
|
if (vox == nullptr) return;
|
||||||
const auto& def = level.content->getIndices()->blocks.require(vox->id);
|
const auto& def = level.content->getIndices()->blocks.require(vox->id);
|
||||||
if (def.grounded) {
|
if (def.grounded) {
|
||||||
const auto& vec = get_ground_direction(def, vox->state.rotation);
|
const auto& vec = get_ground_direction(def, vox->state.rotation);
|
||||||
if (!chunks.isSolidBlock(x + vec.x, y + vec.y, z + vec.z)) {
|
if (!blocks_agent::is_solid_at(chunks, x + vec.x, y + vec.y, z + vec.z)) {
|
||||||
breakBlock(nullptr, def, x, y, z);
|
breakBlock(nullptr, def, x, y, z);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -162,6 +171,13 @@ void BlocksController::randomTick(
|
|||||||
|
|
||||||
void BlocksController::randomTick(int tickid, int parts) {
|
void BlocksController::randomTick(int tickid, int parts) {
|
||||||
auto indices = level.content->getIndices();
|
auto indices = level.content->getIndices();
|
||||||
|
|
||||||
|
std::set<uint64_t> chunksIterated;
|
||||||
|
|
||||||
|
for (const auto& [pid, player] : *level.players) {
|
||||||
|
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;
|
||||||
@ -176,14 +192,27 @@ void BlocksController::randomTick(int tickid, int parts) {
|
|||||||
if (chunk == nullptr || !chunk->flags.lighted) {
|
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
union {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
chunksIterated.insert(posU.key);
|
||||||
randomTick(*chunk, segments, indices);
|
randomTick(*chunk, segments, indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t BlocksController::createBlockInventory(int x, int y, int z) {
|
int64_t BlocksController::createBlockInventory(int x, int y, int z) {
|
||||||
auto chunk = chunks.getChunkByVoxel(x, y, z);
|
auto chunk = blocks_agent::get_chunk(
|
||||||
if (chunk == nullptr) {
|
chunks, floordiv<CHUNK_W>(x), floordiv<CHUNK_D>(z)
|
||||||
|
);
|
||||||
|
if (chunk == nullptr || y < 0 || y >= CHUNK_H) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lx = x - chunk->x * CHUNK_W;
|
int lx = x - chunk->x * CHUNK_W;
|
||||||
@ -203,7 +232,9 @@ int64_t BlocksController::createBlockInventory(int x, int y, int z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BlocksController::bindInventory(int64_t invid, int x, int y, int z) {
|
void BlocksController::bindInventory(int64_t invid, int x, int y, int z) {
|
||||||
auto chunk = chunks.getChunkByVoxel(x, y, z);
|
auto chunk = blocks_agent::get_chunk(
|
||||||
|
chunks, floordiv<CHUNK_W>(x), floordiv<CHUNK_D>(z)
|
||||||
|
);
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
throw std::runtime_error("block does not exists");
|
throw std::runtime_error("block does not exists");
|
||||||
}
|
}
|
||||||
@ -216,7 +247,9 @@ void BlocksController::bindInventory(int64_t invid, int x, int y, int z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BlocksController::unbindInventory(int x, int y, int z) {
|
void BlocksController::unbindInventory(int x, int y, int z) {
|
||||||
auto chunk = chunks.getChunkByVoxel(x, y, z);
|
auto chunk = blocks_agent::get_chunk(
|
||||||
|
chunks, floordiv<CHUNK_W>(x), floordiv<CHUNK_D>(z)
|
||||||
|
);
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
throw std::runtime_error("block does not exists");
|
throw std::runtime_error("block does not exists");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,19 +14,20 @@ class Level;
|
|||||||
class Chunk;
|
class Chunk;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
class Lighting;
|
class Lighting;
|
||||||
|
class GlobalChunks;
|
||||||
class ContentIndices;
|
class ContentIndices;
|
||||||
|
|
||||||
enum class BlockInteraction { step, destruction, placing };
|
enum class BlockInteraction { step, destruction, placing };
|
||||||
|
|
||||||
/// @brief Player argument is nullable
|
/// @brief Player argument is nullable
|
||||||
using on_block_interaction = std::function<
|
using on_block_interaction = std::function<
|
||||||
void(Player*, const glm::ivec3&, const Block&, BlockInteraction type)>;
|
void(Player*, const glm::ivec3&, const Block&, BlockInteraction)>;
|
||||||
|
|
||||||
/// BlocksController manages block updates and data (inventories, metadata)
|
/// BlocksController manages block updates and data (inventories, metadata)
|
||||||
class BlocksController {
|
class BlocksController {
|
||||||
const Level& level;
|
const Level& level;
|
||||||
Chunks& chunks;
|
GlobalChunks& chunks;
|
||||||
Lighting& lighting;
|
Lighting* lighting;
|
||||||
util::Clock randTickClock;
|
util::Clock randTickClock;
|
||||||
util::Clock blocksTickClock;
|
util::Clock blocksTickClock;
|
||||||
util::Clock worldTickClock;
|
util::Clock worldTickClock;
|
||||||
@ -34,7 +35,7 @@ class BlocksController {
|
|||||||
FastRandom random {};
|
FastRandom random {};
|
||||||
std::vector<on_block_interaction> blockInteractionCallbacks;
|
std::vector<on_block_interaction> blockInteractionCallbacks;
|
||||||
public:
|
public:
|
||||||
BlocksController(const Level& level, Lighting& lighting, uint padding);
|
BlocksController(const Level& level, Lighting* lighting, uint padding);
|
||||||
|
|
||||||
void updateSides(int x, int y, int z);
|
void updateSides(int x, int y, int z);
|
||||||
void updateSides(int x, int y, int z, int w, int h, int d);
|
void updateSides(int x, int y, int z, int w, int h, int d);
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "lighting/Lighting.hpp"
|
#include "lighting/Lighting.hpp"
|
||||||
#include "maths/voxmaths.hpp"
|
#include "maths/voxmaths.hpp"
|
||||||
#include "util/timeutil.hpp"
|
#include "util/timeutil.hpp"
|
||||||
|
#include "objects/Player.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
@ -24,8 +25,6 @@ const uint MIN_SURROUNDING = 9;
|
|||||||
|
|
||||||
ChunksController::ChunksController(Level& level, uint padding)
|
ChunksController::ChunksController(Level& level, uint padding)
|
||||||
: level(level),
|
: level(level),
|
||||||
chunks(*level.chunks),
|
|
||||||
lighting(std::make_unique<Lighting>(level.content, level.chunks.get())),
|
|
||||||
padding(padding),
|
padding(padding),
|
||||||
generator(std::make_unique<WorldGenerator>(
|
generator(std::make_unique<WorldGenerator>(
|
||||||
level.content->generators.require(level.getWorld()->getGenerator()),
|
level.content->generators.require(level.getWorld()->getGenerator()),
|
||||||
@ -36,15 +35,19 @@ ChunksController::ChunksController(Level& level, uint padding)
|
|||||||
ChunksController::~ChunksController() = default;
|
ChunksController::~ChunksController() = default;
|
||||||
|
|
||||||
void ChunksController::update(
|
void ChunksController::update(
|
||||||
int64_t maxDuration, int loadDistance, int centerX, int centerY
|
int64_t maxDuration, int loadDistance, Player& player
|
||||||
) {
|
) const {
|
||||||
|
const auto& position = player.getPosition();
|
||||||
|
int centerX = floordiv<CHUNK_W>(position.x);
|
||||||
|
int centerY = floordiv<CHUNK_D>(position.z);
|
||||||
|
|
||||||
generator->update(centerX, centerY, loadDistance);
|
generator->update(centerX, centerY, loadDistance);
|
||||||
|
|
||||||
int64_t mcstotal = 0;
|
int64_t mcstotal = 0;
|
||||||
|
|
||||||
for (uint i = 0; i < MAX_WORK_PER_FRAME; i++) {
|
for (uint i = 0; i < MAX_WORK_PER_FRAME; i++) {
|
||||||
timeutil::Timer timer;
|
timeutil::Timer timer;
|
||||||
if (loadVisible()) {
|
if (loadVisible(player)) {
|
||||||
int64_t mcs = timer.stop();
|
int64_t mcs = timer.stop();
|
||||||
if (mcstotal + mcs < maxDuration * 1000) {
|
if (mcstotal + mcs < maxDuration * 1000) {
|
||||||
mcstotal += mcs;
|
mcstotal += mcs;
|
||||||
@ -55,7 +58,8 @@ void ChunksController::update(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChunksController::loadVisible() {
|
bool ChunksController::loadVisible(const Player& player) const {
|
||||||
|
const auto& chunks = *player.chunks;
|
||||||
int sizeX = chunks.getWidth();
|
int sizeX = chunks.getWidth();
|
||||||
int sizeY = chunks.getHeight();
|
int sizeY = chunks.getHeight();
|
||||||
|
|
||||||
@ -69,7 +73,7 @@ bool ChunksController::loadVisible() {
|
|||||||
auto& chunk = chunks.getChunks()[index];
|
auto& chunk = chunks.getChunks()[index];
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
if (chunk->flags.loaded && !chunk->flags.lighted) {
|
if (chunk->flags.loaded && !chunk->flags.lighted) {
|
||||||
if (buildLights(chunk)) {
|
if (buildLights(player, chunk)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,32 +97,35 @@ bool ChunksController::loadVisible() {
|
|||||||
}
|
}
|
||||||
int offsetX = chunks.getOffsetX();
|
int offsetX = chunks.getOffsetX();
|
||||||
int offsetY = chunks.getOffsetY();
|
int offsetY = chunks.getOffsetY();
|
||||||
createChunk(nearX + offsetX, nearZ + offsetY);
|
createChunk(player, nearX + offsetX, nearZ + offsetY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChunksController::buildLights(const std::shared_ptr<Chunk>& chunk) {
|
bool ChunksController::buildLights(const Player& player, const std::shared_ptr<Chunk>& chunk) const {
|
||||||
int surrounding = 0;
|
int surrounding = 0;
|
||||||
for (int oz = -1; oz <= 1; oz++) {
|
for (int oz = -1; oz <= 1; oz++) {
|
||||||
for (int ox = -1; ox <= 1; ox++) {
|
for (int ox = -1; ox <= 1; ox++) {
|
||||||
if (chunks.getChunk(chunk->x + ox, chunk->z + oz)) surrounding++;
|
if (player.chunks->getChunk(chunk->x + ox, chunk->z + oz))
|
||||||
|
surrounding++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (surrounding == MIN_SURROUNDING) {
|
if (surrounding == MIN_SURROUNDING) {
|
||||||
|
if (lighting) {
|
||||||
bool lightsCache = chunk->flags.loadedLights;
|
bool lightsCache = chunk->flags.loadedLights;
|
||||||
if (!lightsCache) {
|
if (!lightsCache) {
|
||||||
lighting->buildSkyLight(chunk->x, chunk->z);
|
lighting->buildSkyLight(chunk->x, chunk->z);
|
||||||
}
|
}
|
||||||
lighting->onChunkLoaded(chunk->x, chunk->z, !lightsCache);
|
lighting->onChunkLoaded(chunk->x, chunk->z, !lightsCache);
|
||||||
|
}
|
||||||
chunk->flags.lighted = true;
|
chunk->flags.lighted = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChunksController::createChunk(int x, int z) {
|
void ChunksController::createChunk(const Player& player, int x, int z) const {
|
||||||
auto chunk = level.chunksStorage->create(x, z);
|
auto chunk = level.chunksStorage->create(x, z);
|
||||||
chunks.putChunk(chunk);
|
player.chunks->putChunk(chunk);
|
||||||
auto& chunkFlags = chunk->flags;
|
auto& chunkFlags = chunk->flags;
|
||||||
|
|
||||||
if (!chunkFlags.loaded) {
|
if (!chunkFlags.loaded) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
class Level;
|
class Level;
|
||||||
class Chunk;
|
class Chunk;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
|
class Player;
|
||||||
class Lighting;
|
class Lighting;
|
||||||
class WorldGenerator;
|
class WorldGenerator;
|
||||||
|
|
||||||
@ -14,14 +15,13 @@ class WorldGenerator;
|
|||||||
class ChunksController {
|
class ChunksController {
|
||||||
private:
|
private:
|
||||||
Level& level;
|
Level& level;
|
||||||
Chunks& chunks;
|
|
||||||
uint padding;
|
uint padding;
|
||||||
std::unique_ptr<WorldGenerator> generator;
|
std::unique_ptr<WorldGenerator> generator;
|
||||||
|
|
||||||
/// @brief Process one chunk: load it or calculate lights for it
|
/// @brief Process one chunk: load it or calculate lights for it
|
||||||
bool loadVisible();
|
bool loadVisible(const Player& player) const;
|
||||||
bool buildLights(const std::shared_ptr<Chunk>& chunk);
|
bool buildLights(const Player& player, const std::shared_ptr<Chunk>& chunk) const;
|
||||||
void createChunk(int x, int y);
|
void createChunk(const Player& player, int x, int y) const;
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<Lighting> lighting;
|
std::unique_ptr<Lighting> lighting;
|
||||||
|
|
||||||
@ -29,11 +29,7 @@ public:
|
|||||||
~ChunksController();
|
~ChunksController();
|
||||||
|
|
||||||
/// @param maxDuration milliseconds reserved for chunks loading
|
/// @param maxDuration milliseconds reserved for chunks loading
|
||||||
void update(
|
void update(int64_t maxDuration, int loadDistance, Player& player) const;
|
||||||
int64_t maxDuration,
|
|
||||||
int loadDistance,
|
|
||||||
int centerX,
|
|
||||||
int centerY);
|
|
||||||
|
|
||||||
const WorldGenerator* getGenerator() const {
|
const WorldGenerator* getGenerator() const {
|
||||||
return generator.get();
|
return generator.get();
|
||||||
|
|||||||
@ -10,21 +10,33 @@
|
|||||||
#include "objects/Players.hpp"
|
#include "objects/Players.hpp"
|
||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "physics/Hitbox.hpp"
|
#include "physics/Hitbox.hpp"
|
||||||
|
#include "voxels/Chunks.hpp"
|
||||||
#include "scripting/scripting.hpp"
|
#include "scripting/scripting.hpp"
|
||||||
|
#include "lighting/Lighting.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "world/World.hpp"
|
#include "world/World.hpp"
|
||||||
|
|
||||||
static debug::Logger logger("level-control");
|
static debug::Logger logger("level-control");
|
||||||
|
|
||||||
LevelController::LevelController(Engine* engine, std::unique_ptr<Level> levelPtr)
|
LevelController::LevelController(
|
||||||
|
Engine* engine, std::unique_ptr<Level> levelPtr, Player* clientPlayer
|
||||||
|
)
|
||||||
: settings(engine->getSettings()),
|
: settings(engine->getSettings()),
|
||||||
level(std::move(levelPtr)),
|
level(std::move(levelPtr)),
|
||||||
chunks(std::make_unique<ChunksController>(
|
chunks(std::make_unique<ChunksController>(
|
||||||
*level, settings.chunks.padding.get()
|
*level, settings.chunks.padding.get()
|
||||||
)) {
|
)) {
|
||||||
|
|
||||||
|
if (clientPlayer) {
|
||||||
|
chunks->lighting = std::make_unique<Lighting>(
|
||||||
|
level->content, clientPlayer->chunks.get()
|
||||||
|
);
|
||||||
|
}
|
||||||
blocks = std::make_unique<BlocksController>(
|
blocks = std::make_unique<BlocksController>(
|
||||||
*level, *chunks->lighting, settings.chunks.padding.get()
|
*level,
|
||||||
|
chunks ? chunks->lighting.get() : nullptr,
|
||||||
|
settings.chunks.padding.get()
|
||||||
);
|
);
|
||||||
scripting::on_world_load(this);
|
scripting::on_world_load(this);
|
||||||
}
|
}
|
||||||
@ -32,14 +44,15 @@ LevelController::LevelController(Engine* engine, std::unique_ptr<Level> levelPtr
|
|||||||
void LevelController::update(float delta, bool pause) {
|
void LevelController::update(float delta, bool pause) {
|
||||||
for (const auto& [uid, player] : *level->players) {
|
for (const auto& [uid, player] : *level->players) {
|
||||||
glm::vec3 position = player->getPosition();
|
glm::vec3 position = player->getPosition();
|
||||||
level->loadMatrix(
|
player->chunks->configure(
|
||||||
position.x,
|
position.x,
|
||||||
position.z,
|
position.z,
|
||||||
settings.chunks.loadDistance.get() + settings.chunks.padding.get() * 2
|
settings.chunks.loadDistance.get() + settings.chunks.padding.get()
|
||||||
);
|
);
|
||||||
chunks->update(
|
chunks->update(
|
||||||
settings.chunks.loadSpeed.get(), settings.chunks.loadDistance.get(),
|
settings.chunks.loadSpeed.get(),
|
||||||
floordiv(position.x, CHUNK_W), floordiv(position.z, CHUNK_D)
|
settings.chunks.loadDistance.get(),
|
||||||
|
*player
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!pause) {
|
if (!pause) {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class LevelController {
|
|||||||
std::unique_ptr<BlocksController> blocks;
|
std::unique_ptr<BlocksController> blocks;
|
||||||
std::unique_ptr<ChunksController> chunks;
|
std::unique_ptr<ChunksController> chunks;
|
||||||
public:
|
public:
|
||||||
LevelController(Engine* engine, std::unique_ptr<Level> level);
|
LevelController(Engine* engine, std::unique_ptr<Level> level, Player* clientPlayer);
|
||||||
|
|
||||||
/// @param delta time elapsed since the last update
|
/// @param delta time elapsed since the last update
|
||||||
/// @param pause is world and player simulation paused
|
/// @param pause is world and player simulation paused
|
||||||
|
|||||||
@ -215,7 +215,7 @@ void PlayerController::onFootstep(const Hitbox& hitbox) {
|
|||||||
int x = std::floor(pos.x + half.x * offsetX);
|
int x = std::floor(pos.x + half.x * offsetX);
|
||||||
int y = std::floor(pos.y - half.y * 1.1f);
|
int y = std::floor(pos.y - half.y * 1.1f);
|
||||||
int z = std::floor(pos.z + half.z * offsetZ);
|
int z = std::floor(pos.z + half.z * offsetZ);
|
||||||
auto vox = level->chunks->get(x, y, z);
|
auto vox = player->chunks->get(x, y, z);
|
||||||
if (vox) {
|
if (vox) {
|
||||||
auto& def = level->content->getIndices()->blocks.require(vox->id);
|
auto& def = level->content->getIndices()->blocks.require(vox->id);
|
||||||
if (!def.obstacle) {
|
if (!def.obstacle) {
|
||||||
@ -274,7 +274,7 @@ void PlayerController::postUpdate(float delta, bool input, bool pause) {
|
|||||||
camControl.updateMouse(this->input);
|
camControl.updateMouse(this->input);
|
||||||
}
|
}
|
||||||
player->postUpdate();
|
player->postUpdate();
|
||||||
camControl.update(this->input, pause ? 0.0f : delta, level->chunks.get());
|
camControl.update(this->input, pause ? 0.0f : delta, player->chunks.get());
|
||||||
if (input) {
|
if (input) {
|
||||||
updateInteraction(delta);
|
updateInteraction(delta);
|
||||||
} else {
|
} else {
|
||||||
@ -366,14 +366,14 @@ static void pick_block(
|
|||||||
|
|
||||||
voxel* PlayerController::updateSelection(float maxDistance) {
|
voxel* PlayerController::updateSelection(float maxDistance) {
|
||||||
auto indices = level->content->getIndices();
|
auto indices = level->content->getIndices();
|
||||||
auto chunks = level->chunks.get();
|
auto& chunks = *player->chunks;
|
||||||
auto camera = player->fpCamera.get();
|
auto camera = player->fpCamera.get();
|
||||||
auto& selection = player->selection;
|
auto& selection = player->selection;
|
||||||
|
|
||||||
glm::vec3 end;
|
glm::vec3 end;
|
||||||
glm::ivec3 iend;
|
glm::ivec3 iend;
|
||||||
glm::ivec3 norm;
|
glm::ivec3 norm;
|
||||||
voxel* vox = chunks->rayCast(
|
voxel* vox = chunks.rayCast(
|
||||||
camera->position, camera->front, maxDistance, end, norm, iend
|
camera->position, camera->front, maxDistance, end, norm, iend
|
||||||
);
|
);
|
||||||
if (vox) {
|
if (vox) {
|
||||||
@ -411,12 +411,12 @@ voxel* PlayerController::updateSelection(float maxDistance) {
|
|||||||
blockstate selectedState = vox->state;
|
blockstate selectedState = vox->state;
|
||||||
selection.vox = *vox;
|
selection.vox = *vox;
|
||||||
if (selectedState.segment) {
|
if (selectedState.segment) {
|
||||||
selection.position = chunks->seekOrigin(
|
selection.position = chunks.seekOrigin(
|
||||||
iend, indices->blocks.require(selection.vox.id), selectedState
|
iend, indices->blocks.require(selection.vox.id), selectedState
|
||||||
);
|
);
|
||||||
auto origin = chunks->get(selection.position);
|
auto origin = chunks.get(selection.position);
|
||||||
if (origin && origin->id != vox->id) {
|
if (origin && origin->id != vox->id) {
|
||||||
chunks->set(iend.x, iend.y, iend.z, 0, {});
|
chunks.set(iend.x, iend.y, iend.z, 0, {});
|
||||||
return updateSelection(maxDistance);
|
return updateSelection(maxDistance);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -429,7 +429,7 @@ voxel* PlayerController::updateSelection(float maxDistance) {
|
|||||||
|
|
||||||
void PlayerController::processRightClick(const Block& def, const Block& target) {
|
void PlayerController::processRightClick(const Block& def, const Block& target) {
|
||||||
const auto& selection = player->selection;
|
const auto& selection = player->selection;
|
||||||
auto chunks = level->chunks.get();
|
auto& chunks = *player->chunks;
|
||||||
auto camera = player->fpCamera.get();
|
auto camera = player->fpCamera.get();
|
||||||
|
|
||||||
blockstate state {};
|
blockstate state {};
|
||||||
@ -458,16 +458,16 @@ void PlayerController::processRightClick(const Block& def, const Block& target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto vox = chunks->get(coord);
|
auto vox = chunks.get(coord);
|
||||||
if (vox == nullptr) {
|
if (vox == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!chunks->checkReplaceability(def, state, coord)) {
|
if (!chunks.checkReplaceability(def, state, coord)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (def.grounded) {
|
if (def.grounded) {
|
||||||
const auto& vec = get_ground_direction(def, state.rotation);
|
const auto& vec = get_ground_direction(def, state.rotation);
|
||||||
if (!chunks->isSolidBlock(
|
if (!chunks.isSolidBlock(
|
||||||
coord.x + vec.x, coord.y + vec.y, coord.z + vec.z
|
coord.x + vec.x, coord.y + vec.y, coord.z + vec.z
|
||||||
)) {
|
)) {
|
||||||
return;
|
return;
|
||||||
@ -502,7 +502,7 @@ void PlayerController::updateEntityInteraction(
|
|||||||
|
|
||||||
void PlayerController::updateInteraction(float delta) {
|
void PlayerController::updateInteraction(float delta) {
|
||||||
auto indices = level->content->getIndices();
|
auto indices = level->content->getIndices();
|
||||||
auto chunks = level->chunks.get();
|
auto chunks = player->chunks.get();
|
||||||
const auto& selection = player->selection;
|
const auto& selection = player->selection;
|
||||||
|
|
||||||
if (interactionTimer > 0.0f) {
|
if (interactionTimer > 0.0f) {
|
||||||
|
|||||||
@ -40,7 +40,9 @@ static int l_is_solid_at(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
return lua::pushboolean(L, blocks_agent::is_solid_at(*level->chunks, x, y, z));
|
return lua::pushboolean(
|
||||||
|
L, blocks_agent::is_solid_at(*level->chunksStorage, x, y, z)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_count(lua::State* L) {
|
static int l_count(lua::State* L) {
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "physics/Hitbox.hpp"
|
#include "physics/Hitbox.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
|
#include "voxels/blocks_agent.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
|
|
||||||
using namespace scripting;
|
using namespace scripting;
|
||||||
@ -149,8 +150,15 @@ static int l_raycast(lua::State* L) {
|
|||||||
|
|
||||||
blockid_t block = BLOCK_VOID;
|
blockid_t block = BLOCK_VOID;
|
||||||
|
|
||||||
if (auto voxel = level->chunks->rayCast(
|
if (auto voxel = blocks_agent::raycast(
|
||||||
start, dir, maxDistance, end, normal, iend, filteredBlocks
|
*level->chunksStorage,
|
||||||
|
start,
|
||||||
|
dir,
|
||||||
|
maxDistance,
|
||||||
|
end,
|
||||||
|
normal,
|
||||||
|
iend,
|
||||||
|
filteredBlocks
|
||||||
)) {
|
)) {
|
||||||
maxDistance = glm::distance(start, end);
|
maxDistance = glm::distance(start, end);
|
||||||
block = voxel->id;
|
block = voxel->id;
|
||||||
|
|||||||
@ -28,7 +28,7 @@ static int l_create_fragment(lua::State* L) {
|
|||||||
bool saveEntities = lua::toboolean(L, 4);
|
bool saveEntities = lua::toboolean(L, 4);
|
||||||
|
|
||||||
auto fragment =
|
auto fragment =
|
||||||
VoxelFragment::create(level, pointA, pointB, crop, saveEntities);
|
VoxelFragment::create(*level, pointA, pointB, crop, saveEntities);
|
||||||
return lua::newuserdata<lua::LuaVoxelFragment>(
|
return lua::newuserdata<lua::LuaVoxelFragment>(
|
||||||
L, std::shared_ptr<VoxelFragment>(std::move(fragment))
|
L, std::shared_ptr<VoxelFragment>(std::move(fragment))
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "voxels/voxel.hpp"
|
#include "voxels/voxel.hpp"
|
||||||
|
#include "voxels/blocks_agent.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "api_lua.hpp"
|
#include "api_lua.hpp"
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ static int l_open_block(lua::State* L) {
|
|||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
bool playerInventory = !lua::toboolean(L, 4);
|
bool playerInventory = !lua::toboolean(L, 4);
|
||||||
|
|
||||||
auto vox = level->chunks->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
if (vox == nullptr) {
|
if (vox == nullptr) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"block does not exists at " + std::to_string(x) + " " +
|
"block does not exists at " + std::to_string(x) + " " +
|
||||||
|
|||||||
@ -125,7 +125,7 @@ static int l_get_generator(lua::State* L) {
|
|||||||
static int l_get_chunk_data(lua::State* L) {
|
static int l_get_chunk_data(lua::State* L) {
|
||||||
int x = (int)lua::tointeger(L, 1);
|
int x = (int)lua::tointeger(L, 1);
|
||||||
int y = (int)lua::tointeger(L, 2);
|
int y = (int)lua::tointeger(L, 2);
|
||||||
const auto& chunk = level->chunks->getChunk(x, y);
|
const auto& chunk = level->chunksStorage->getChunk(x, y);
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
lua::pushnil(L);
|
lua::pushnil(L);
|
||||||
return 0;
|
return 0;
|
||||||
@ -181,8 +181,8 @@ static int l_set_chunk_data(lua::State* L) {
|
|||||||
if (lua::gettop(L) >= 4) {
|
if (lua::gettop(L) >= 4) {
|
||||||
is_compressed = lua::toboolean(L, 4);
|
is_compressed = lua::toboolean(L, 4);
|
||||||
}
|
}
|
||||||
auto chunk = level->chunks->getChunk(x, y);
|
auto chunk = level->chunksStorage->getChunk(x, y);
|
||||||
if(chunk== nullptr){
|
if (chunk == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (is_compressed) {
|
if (is_compressed) {
|
||||||
@ -217,22 +217,22 @@ static int l_set_chunk_data(lua::State* L) {
|
|||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
lighting.onChunkLoaded(x, y, true);
|
lighting.onChunkLoaded(x, y, true);
|
||||||
|
|
||||||
chunk = level->chunks->getChunk(x - 1, y);
|
chunk = level->chunksStorage->getChunk(x - 1, y);
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
lighting.onChunkLoaded(x - 1, y, true);
|
lighting.onChunkLoaded(x - 1, y, true);
|
||||||
}
|
}
|
||||||
chunk = level->chunks->getChunk(x + 1, y);
|
chunk = level->chunksStorage->getChunk(x + 1, y);
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
lighting.onChunkLoaded(x + 1, y, true);
|
lighting.onChunkLoaded(x + 1, y, true);
|
||||||
}
|
}
|
||||||
chunk = level->chunks->getChunk(x, y - 1);
|
chunk = level->chunksStorage->getChunk(x, y - 1);
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
lighting.onChunkLoaded(x, y - 1, true);
|
lighting.onChunkLoaded(x, y - 1, true);
|
||||||
}
|
}
|
||||||
chunk = level->chunks->getChunk(x, y + 1);
|
chunk = level->chunksStorage->getChunk(x, y + 1);
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
lighting.onChunkLoaded(x, y + 1, true);
|
lighting.onChunkLoaded(x, y + 1, true);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ static int l_place(lua::State* L) {
|
|||||||
auto offset = tovec3(L, 2);
|
auto offset = tovec3(L, 2);
|
||||||
int rotation = tointeger(L, 3) & 0b11;
|
int rotation = tointeger(L, 3) & 0b11;
|
||||||
fragment->getFragment()->place(
|
fragment->getFragment()->place(
|
||||||
*scripting::level->chunks, offset, rotation
|
*scripting::level->chunksStorage, offset, rotation
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -459,7 +459,7 @@ void Entities::updatePhysics(float delta) {
|
|||||||
float vel = glm::length(prevVel);
|
float vel = glm::length(prevVel);
|
||||||
int substeps = static_cast<int>(delta * vel * 20);
|
int substeps = static_cast<int>(delta * vel * 20);
|
||||||
substeps = std::min(100, std::max(2, substeps));
|
substeps = std::min(100, std::max(2, substeps));
|
||||||
physics->step(level->chunks.get(), &hitbox, delta, substeps, eid.uid);
|
physics->step(*level->chunksStorage, &hitbox, delta, substeps, eid.uid);
|
||||||
hitbox.linearDamping = hitbox.grounded * 24;
|
hitbox.linearDamping = hitbox.grounded * 24;
|
||||||
transform.setPos(hitbox.position);
|
transform.setPos(hitbox.position);
|
||||||
if (hitbox.grounded && !grounded) {
|
if (hitbox.grounded && !grounded) {
|
||||||
|
|||||||
@ -205,12 +205,12 @@ void Player::attemptToFindSpawnpoint() {
|
|||||||
position.z + (rand() % 200 - 100)
|
position.z + (rand() % 200 - 100)
|
||||||
);
|
);
|
||||||
while (newpos.y > 0 &&
|
while (newpos.y > 0 &&
|
||||||
!level->chunks->isObstacleBlock(newpos.x, newpos.y - 2, newpos.z)) {
|
!chunks->isObstacleBlock(newpos.x, newpos.y - 2, newpos.z)) {
|
||||||
newpos.y--;
|
newpos.y--;
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel* headvox = level->chunks->get(newpos.x, newpos.y + 1, newpos.z);
|
voxel* headvox = chunks->get(newpos.x, newpos.y + 1, newpos.z);
|
||||||
if (level->chunks->isObstacleBlock(newpos.x, newpos.y, newpos.z) ||
|
if (chunks->isObstacleBlock(newpos.x, newpos.y, newpos.z) ||
|
||||||
headvox == nullptr || headvox->id != 0) {
|
headvox == nullptr || headvox->id != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "maths/aabb.hpp"
|
#include "maths/aabb.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/GlobalChunks.hpp"
|
||||||
#include "voxels/voxel.hpp"
|
#include "voxels/voxel.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -18,7 +18,7 @@ PhysicsSolver::PhysicsSolver(glm::vec3 gravity) : gravity(gravity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSolver::step(
|
void PhysicsSolver::step(
|
||||||
Chunks* chunks,
|
const GlobalChunks& chunks,
|
||||||
Hitbox* hitbox,
|
Hitbox* hitbox,
|
||||||
float delta,
|
float delta,
|
||||||
uint substeps,
|
uint substeps,
|
||||||
@ -63,7 +63,7 @@ void PhysicsSolver::step(
|
|||||||
float x = (px-half.x+E) + ix * s;
|
float x = (px-half.x+E) + ix * s;
|
||||||
for (int iz = 0; iz <= (half.z-E)*2/s; iz++){
|
for (int iz = 0; iz <= (half.z-E)*2/s; iz++){
|
||||||
float z = (pos.z-half.z+E) + iz * s;
|
float z = (pos.z-half.z+E) + iz * s;
|
||||||
if (chunks->isObstacleAt(x,y,z)){
|
if (chunks.isObstacleAt(x,y,z)){
|
||||||
hitbox->grounded = true;
|
hitbox->grounded = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ void PhysicsSolver::step(
|
|||||||
float x = (pos.x-half.x+E) + ix * s;
|
float x = (pos.x-half.x+E) + ix * s;
|
||||||
for (int iz = 0; iz <= (half.z-E)*2/s; iz++){
|
for (int iz = 0; iz <= (half.z-E)*2/s; iz++){
|
||||||
float z = (pz-half.z+E) + iz * s;
|
float z = (pz-half.z+E) + iz * s;
|
||||||
if (chunks->isObstacleAt(x,y,z)){
|
if (chunks.isObstacleAt(x,y,z)){
|
||||||
hitbox->grounded = true;
|
hitbox->grounded = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -119,8 +119,8 @@ void PhysicsSolver::step(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static float calc_step_height(
|
static float calc_step_height(
|
||||||
Chunks* chunks,
|
const GlobalChunks& chunks,
|
||||||
glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::vec3& half,
|
const glm::vec3& half,
|
||||||
float stepHeight,
|
float stepHeight,
|
||||||
float s
|
float s
|
||||||
@ -130,7 +130,7 @@ static float calc_step_height(
|
|||||||
float x = (pos.x-half.x+E) + ix * s;
|
float x = (pos.x-half.x+E) + ix * s;
|
||||||
for (int iz = 0; iz <= (half.z-E)*2/s; iz++) {
|
for (int iz = 0; iz <= (half.z-E)*2/s; iz++) {
|
||||||
float z = (pos.z-half.z+E) + iz * s;
|
float z = (pos.z-half.z+E) + iz * s;
|
||||||
if (chunks->isObstacleAt(x, pos.y+half.y+stepHeight, z)) {
|
if (chunks.isObstacleAt(x, pos.y+half.y+stepHeight, z)) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ static float calc_step_height(
|
|||||||
|
|
||||||
template <int nx, int ny, int nz>
|
template <int nx, int ny, int nz>
|
||||||
static bool calc_collision_neg(
|
static bool calc_collision_neg(
|
||||||
Chunks* chunks,
|
const GlobalChunks& chunks,
|
||||||
glm::vec3& pos,
|
glm::vec3& pos,
|
||||||
glm::vec3& vel,
|
glm::vec3& vel,
|
||||||
const glm::vec3& half,
|
const glm::vec3& half,
|
||||||
@ -159,7 +159,7 @@ static bool calc_collision_neg(
|
|||||||
coord[nz] = (pos[nz]-half[nz]+E) + iz * s;
|
coord[nz] = (pos[nz]-half[nz]+E) + iz * s;
|
||||||
coord[nx] = (pos[nx]-half[nx]-E);
|
coord[nx] = (pos[nx]-half[nx]-E);
|
||||||
|
|
||||||
if (const auto aabb = chunks->isObstacleAt(coord.x, coord.y, coord.z)) {
|
if (const auto aabb = chunks.isObstacleAt(coord.x, coord.y, coord.z)) {
|
||||||
vel[nx] = 0.0f;
|
vel[nx] = 0.0f;
|
||||||
float newx = std::floor(coord[nx]) + aabb->max()[nx] + half[nx] + E;
|
float newx = std::floor(coord[nx]) + aabb->max()[nx] + half[nx] + E;
|
||||||
if (std::abs(newx-pos[nx]) <= MAX_FIX) {
|
if (std::abs(newx-pos[nx]) <= MAX_FIX) {
|
||||||
@ -174,7 +174,7 @@ static bool calc_collision_neg(
|
|||||||
|
|
||||||
template <int nx, int ny, int nz>
|
template <int nx, int ny, int nz>
|
||||||
static void calc_collision_pos(
|
static void calc_collision_pos(
|
||||||
Chunks* chunks,
|
const GlobalChunks& chunks,
|
||||||
glm::vec3& pos,
|
glm::vec3& pos,
|
||||||
glm::vec3& vel,
|
glm::vec3& vel,
|
||||||
const glm::vec3& half,
|
const glm::vec3& half,
|
||||||
@ -191,7 +191,7 @@ static void calc_collision_pos(
|
|||||||
for (int iz = 0; iz <= (half[nz]-E)*2/s; iz++) {
|
for (int iz = 0; iz <= (half[nz]-E)*2/s; iz++) {
|
||||||
coord[nz] = (pos[nz]-half[nz]+E) + iz * s;
|
coord[nz] = (pos[nz]-half[nz]+E) + iz * s;
|
||||||
coord[nx] = (pos[nx]+half[nx]+E);
|
coord[nx] = (pos[nx]+half[nx]+E);
|
||||||
if (const auto aabb = chunks->isObstacleAt(coord.x, coord.y, coord.z)) {
|
if (const auto aabb = chunks.isObstacleAt(coord.x, coord.y, coord.z)) {
|
||||||
vel[nx] = 0.0f;
|
vel[nx] = 0.0f;
|
||||||
float newx = std::floor(coord[nx]) - half[nx] + aabb->min()[nx] - E;
|
float newx = std::floor(coord[nx]) - half[nx] + aabb->min()[nx] - E;
|
||||||
if (std::abs(newx-pos[nx]) <= MAX_FIX) {
|
if (std::abs(newx-pos[nx]) <= MAX_FIX) {
|
||||||
@ -204,7 +204,7 @@ static void calc_collision_pos(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSolver::colisionCalc(
|
void PhysicsSolver::colisionCalc(
|
||||||
Chunks* chunks,
|
const GlobalChunks& chunks,
|
||||||
Hitbox* hitbox,
|
Hitbox* hitbox,
|
||||||
glm::vec3& vel,
|
glm::vec3& vel,
|
||||||
glm::vec3& pos,
|
glm::vec3& pos,
|
||||||
@ -234,7 +234,7 @@ void PhysicsSolver::colisionCalc(
|
|||||||
for (int iz = 0; iz <= (half.z-E)*2/s; iz++) {
|
for (int iz = 0; iz <= (half.z-E)*2/s; iz++) {
|
||||||
float z = (pos.z-half.z+E) + iz * s;
|
float z = (pos.z-half.z+E) + iz * s;
|
||||||
float y = (pos.y-half.y+E);
|
float y = (pos.y-half.y+E);
|
||||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
if ((aabb = chunks.isObstacleAt(x,y,z))){
|
||||||
vel.y = 0.0f;
|
vel.y = 0.0f;
|
||||||
float newy = std::floor(y) + aabb->max().y + half.y;
|
float newy = std::floor(y) + aabb->max().y + half.y;
|
||||||
if (std::abs(newy-pos.y) <= MAX_FIX+stepHeight) {
|
if (std::abs(newy-pos.y) <= MAX_FIX+stepHeight) {
|
||||||
@ -251,7 +251,7 @@ void PhysicsSolver::colisionCalc(
|
|||||||
for (int iz = 0; iz <= (half.z-E)*2/s; iz++) {
|
for (int iz = 0; iz <= (half.z-E)*2/s; iz++) {
|
||||||
float z = (pos.z-half.z+E) + iz * s;
|
float z = (pos.z-half.z+E) + iz * s;
|
||||||
float y = (pos.y+half.y+E);
|
float y = (pos.y+half.y+E);
|
||||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
if ((aabb = chunks.isObstacleAt(x,y,z))){
|
||||||
vel.y = 0.0f;
|
vel.y = 0.0f;
|
||||||
float newy = std::floor(y) - half.y + aabb->min().y - E;
|
float newy = std::floor(y) - half.y + aabb->min().y - E;
|
||||||
if (std::abs(newy-pos.y) <= MAX_FIX) {
|
if (std::abs(newy-pos.y) <= MAX_FIX) {
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class Block;
|
class Block;
|
||||||
class Chunks;
|
class GlobalChunks;
|
||||||
struct Sensor;
|
struct Sensor;
|
||||||
|
|
||||||
class PhysicsSolver {
|
class PhysicsSolver {
|
||||||
@ -18,14 +18,14 @@ class PhysicsSolver {
|
|||||||
public:
|
public:
|
||||||
PhysicsSolver(glm::vec3 gravity);
|
PhysicsSolver(glm::vec3 gravity);
|
||||||
void step(
|
void step(
|
||||||
Chunks* chunks,
|
const GlobalChunks& chunks,
|
||||||
Hitbox* hitbox,
|
Hitbox* hitbox,
|
||||||
float delta,
|
float delta,
|
||||||
uint substeps,
|
uint substeps,
|
||||||
entityid_t entity
|
entityid_t entity
|
||||||
);
|
);
|
||||||
void colisionCalc(
|
void colisionCalc(
|
||||||
Chunks* chunks,
|
const GlobalChunks& chunks,
|
||||||
Hitbox* hitbox,
|
Hitbox* hitbox,
|
||||||
glm::vec3& vel,
|
glm::vec3& vel,
|
||||||
glm::vec3& pos,
|
glm::vec3& pos,
|
||||||
|
|||||||
@ -38,6 +38,14 @@ Chunks::Chunks(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Chunks::configure(int32_t x, int32_t z, uint32_t radius) {
|
||||||
|
setCenter(x, z);
|
||||||
|
uint32_t diameter = radius * 2LL;
|
||||||
|
if (getWidth() != diameter) {
|
||||||
|
resize(diameter, diameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
||||||
return blocks_agent::get(*this, x, y, z);
|
return blocks_agent::get(*this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,8 @@ public:
|
|||||||
);
|
);
|
||||||
~Chunks() = default;
|
~Chunks() = default;
|
||||||
|
|
||||||
|
void configure(int32_t x, int32_t z, uint32_t radius);
|
||||||
|
|
||||||
bool putChunk(const std::shared_ptr<Chunk>& chunk);
|
bool putChunk(const std::shared_ptr<Chunk>& chunk);
|
||||||
|
|
||||||
Chunk* getChunk(int32_t x, int32_t z) const;
|
Chunk* getChunk(int32_t x, int32_t z) const;
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "lighting/Lightmap.hpp"
|
#include "lighting/Lightmap.hpp"
|
||||||
#include "maths/voxmaths.hpp"
|
#include "maths/voxmaths.hpp"
|
||||||
#include "objects/Entities.hpp"
|
#include "objects/Entities.hpp"
|
||||||
|
#include "voxels/blocks_agent.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "world/World.hpp"
|
#include "world/World.hpp"
|
||||||
@ -198,3 +199,7 @@ void GlobalChunks::saveAll() {
|
|||||||
void GlobalChunks::putChunk(std::shared_ptr<Chunk> chunk) {
|
void GlobalChunks::putChunk(std::shared_ptr<Chunk> chunk) {
|
||||||
chunksMap[keyfrom(chunk->x, chunk->z)] = std::move(chunk);
|
chunksMap[keyfrom(chunk->x, chunk->z)] = std::move(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AABB* GlobalChunks::isObstacleAt(float x, float y, float z) const {
|
||||||
|
return blocks_agent::is_obstacle_at(*this, x, y, z);
|
||||||
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
class Chunk;
|
class Chunk;
|
||||||
class Level;
|
class Level;
|
||||||
|
struct AABB;
|
||||||
class ContentIndices;
|
class ContentIndices;
|
||||||
|
|
||||||
class GlobalChunks {
|
class GlobalChunks {
|
||||||
@ -51,6 +52,8 @@ public:
|
|||||||
|
|
||||||
void putChunk(std::shared_ptr<Chunk> chunk);
|
void putChunk(std::shared_ptr<Chunk> chunk);
|
||||||
|
|
||||||
|
const AABB* isObstacleAt(float x, float y, float z) const;
|
||||||
|
|
||||||
inline Chunk* getChunk(int cx, int cz) const {
|
inline Chunk* getChunk(int cx, int cz) const {
|
||||||
const auto& found = chunksMap.find(keyfrom(cx, cz));
|
const auto& found = chunksMap.find(keyfrom(cx, cz));
|
||||||
if (found == chunksMap.end()) {
|
if (found == chunksMap.end()) {
|
||||||
|
|||||||
@ -265,3 +265,105 @@ voxel* blocks_agent::raycast(
|
|||||||
) {
|
) {
|
||||||
return raycast_blocks(chunks, start, dir, maxDist, end, norm, iend, filter);
|
return raycast_blocks(chunks, start, dir, maxDist, end, norm, iend, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reduce nesting on next modification
|
||||||
|
// 25.06.2024: not now
|
||||||
|
// 11.11.2024: not now
|
||||||
|
template <class Storage>
|
||||||
|
inline void get_voxels_impl(
|
||||||
|
const Storage& chunks, VoxelsVolume* volume, bool backlight
|
||||||
|
) {
|
||||||
|
const auto& blocks = chunks.getContentIndices().blocks;
|
||||||
|
voxel* voxels = volume->getVoxels();
|
||||||
|
light_t* lights = volume->getLights();
|
||||||
|
int x = volume->getX();
|
||||||
|
int y = volume->getY();
|
||||||
|
int z = volume->getZ();
|
||||||
|
|
||||||
|
int w = volume->getW();
|
||||||
|
int h = volume->getH();
|
||||||
|
int d = volume->getD();
|
||||||
|
|
||||||
|
int scx = floordiv<CHUNK_W>(x);
|
||||||
|
int scz = floordiv<CHUNK_D>(z);
|
||||||
|
|
||||||
|
int ecx = floordiv<CHUNK_W>(x + w);
|
||||||
|
int ecz = floordiv<CHUNK_D>(z + d);
|
||||||
|
|
||||||
|
int cw = ecx - scx + 1;
|
||||||
|
int cd = ecz - scz + 1;
|
||||||
|
|
||||||
|
// cw*cd chunks will be scanned
|
||||||
|
for (int cz = scz; cz < scz + cd; cz++) {
|
||||||
|
for (int cx = scx; cx < scx + cw; cx++) {
|
||||||
|
const auto chunk = get_chunk(chunks, cx, cz);
|
||||||
|
if (chunk == nullptr) {
|
||||||
|
// no chunk loaded -> filling with BLOCK_VOID
|
||||||
|
for (int ly = y; ly < y + h; ly++) {
|
||||||
|
for (int lz = std::max(z, cz * CHUNK_D);
|
||||||
|
lz < std::min(z + d, (cz + 1) * CHUNK_D);
|
||||||
|
lz++) {
|
||||||
|
for (int lx = std::max(x, cx * CHUNK_W);
|
||||||
|
lx < std::min(x + w, (cx + 1) * CHUNK_W);
|
||||||
|
lx++) {
|
||||||
|
uint idx = vox_index(lx - x, ly - y, lz - z, w, d);
|
||||||
|
voxels[idx].id = BLOCK_VOID;
|
||||||
|
lights[idx] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const voxel* cvoxels = chunk->voxels;
|
||||||
|
const light_t* clights = chunk->lightmap.getLights();
|
||||||
|
for (int ly = y; ly < y + h; ly++) {
|
||||||
|
for (int lz = std::max(z, cz * CHUNK_D);
|
||||||
|
lz < std::min(z + d, (cz + 1) * CHUNK_D);
|
||||||
|
lz++) {
|
||||||
|
for (int lx = std::max(x, cx * CHUNK_W);
|
||||||
|
lx < std::min(x + w, (cx + 1) * CHUNK_W);
|
||||||
|
lx++) {
|
||||||
|
uint vidx = vox_index(lx - x, ly - y, lz - z, w, d);
|
||||||
|
uint cidx = vox_index(
|
||||||
|
lx - cx * CHUNK_W,
|
||||||
|
ly,
|
||||||
|
lz - cz * CHUNK_D,
|
||||||
|
CHUNK_W,
|
||||||
|
CHUNK_D
|
||||||
|
);
|
||||||
|
voxels[vidx] = cvoxels[cidx];
|
||||||
|
light_t light = clights[cidx];
|
||||||
|
if (backlight) {
|
||||||
|
const auto block = blocks.get(voxels[vidx].id);
|
||||||
|
if (block && block->lightPassing) {
|
||||||
|
light = Lightmap::combine(
|
||||||
|
std::min(15,
|
||||||
|
Lightmap::extract(light, 0) + 1),
|
||||||
|
std::min(15,
|
||||||
|
Lightmap::extract(light, 1) + 1),
|
||||||
|
std::min(15,
|
||||||
|
Lightmap::extract(light, 2) + 1),
|
||||||
|
std::min(15,
|
||||||
|
static_cast<int>(Lightmap::extract(light, 3)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lights[vidx] = light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void blocks_agent::get_voxels(
|
||||||
|
const Chunks& chunks, VoxelsVolume* volume, bool backlight
|
||||||
|
) {
|
||||||
|
get_voxels_impl(chunks, volume, backlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void blocks_agent::get_voxels(
|
||||||
|
const GlobalChunks& chunks, VoxelsVolume* volume, bool backlight
|
||||||
|
) {
|
||||||
|
get_voxels_impl(chunks, volume, backlight);
|
||||||
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "Block.hpp"
|
#include "Block.hpp"
|
||||||
#include "Chunk.hpp"
|
#include "Chunk.hpp"
|
||||||
#include "Chunks.hpp"
|
#include "Chunks.hpp"
|
||||||
|
#include "VoxelsVolume.hpp"
|
||||||
#include "GlobalChunks.hpp"
|
#include "GlobalChunks.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
@ -17,6 +18,8 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
struct AABB;
|
||||||
|
|
||||||
namespace blocks_agent {
|
namespace blocks_agent {
|
||||||
|
|
||||||
/// @brief Get specified chunk.
|
/// @brief Get specified chunk.
|
||||||
@ -432,4 +435,42 @@ voxel* raycast(
|
|||||||
std::set<blockid_t> filter
|
std::set<blockid_t> filter
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void get_voxels(const Chunks& chunks, VoxelsVolume* volume, bool backlight=false);
|
||||||
|
|
||||||
|
void get_voxels(const GlobalChunks& chunks, VoxelsVolume* volume, bool backlight=false);
|
||||||
|
|
||||||
|
template <class Storage>
|
||||||
|
inline const AABB* is_obstacle_at(const Storage& chunks, float x, float y, float z) {
|
||||||
|
int ix = std::floor(x);
|
||||||
|
int iy = std::floor(y);
|
||||||
|
int iz = std::floor(z);
|
||||||
|
voxel* v = get(chunks, ix, iy, iz);
|
||||||
|
if (v == nullptr) {
|
||||||
|
if (iy >= CHUNK_H) {
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
static const AABB empty;
|
||||||
|
return ∅
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto& def = chunks.getContentIndices().blocks.require(v->id);
|
||||||
|
if (def.obstacle) {
|
||||||
|
glm::ivec3 offset {};
|
||||||
|
if (v->state.segment) {
|
||||||
|
glm::ivec3 point(ix, iy, iz);
|
||||||
|
offset = seek_origin(chunks, point, def, v->state) - point;
|
||||||
|
}
|
||||||
|
const auto& boxes =
|
||||||
|
def.rotatable ? def.rt.hitboxes[v->state.rotation] : def.hitboxes;
|
||||||
|
for (const auto& hitbox : boxes) {
|
||||||
|
if (hitbox.contains(
|
||||||
|
{x - ix - offset.x, y - iy - offset.y, z - iz - offset.z}
|
||||||
|
)) {
|
||||||
|
return &hitbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
} // blocks_agent
|
} // blocks_agent
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
#include "data/dv_util.hpp"
|
#include "data/dv_util.hpp"
|
||||||
#include "items/Inventories.hpp"
|
#include "items/Inventories.hpp"
|
||||||
#include "items/Inventory.hpp"
|
#include "items/Inventory.hpp"
|
||||||
#include "lighting/Lighting.hpp"
|
|
||||||
#include "objects/Entities.hpp"
|
#include "objects/Entities.hpp"
|
||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "objects/Players.hpp"
|
#include "objects/Players.hpp"
|
||||||
@ -12,7 +11,6 @@
|
|||||||
#include "physics/PhysicsSolver.hpp"
|
#include "physics/PhysicsSolver.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
|
||||||
#include "voxels/GlobalChunks.hpp"
|
#include "voxels/GlobalChunks.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
#include "LevelEvents.hpp"
|
#include "LevelEvents.hpp"
|
||||||
@ -60,31 +58,11 @@ Level::Level(
|
|||||||
events->listen(LevelEventType::EVT_CHUNK_HIDDEN, [this](LevelEventType, Chunk* chunk) {
|
events->listen(LevelEventType::EVT_CHUNK_HIDDEN, [this](LevelEventType, Chunk* chunk) {
|
||||||
chunksStorage->decref(chunk);
|
chunksStorage->decref(chunk);
|
||||||
});
|
});
|
||||||
|
|
||||||
uint matrixSize =
|
|
||||||
(settings.chunks.loadDistance.get() + settings.chunks.padding.get()) *
|
|
||||||
2;
|
|
||||||
chunks = std::make_unique<Chunks>(
|
|
||||||
matrixSize, matrixSize, 0, 0, events.get(), content->getIndices()
|
|
||||||
);
|
|
||||||
|
|
||||||
inventories = std::make_unique<Inventories>(*this);
|
inventories = std::make_unique<Inventories>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Level::~Level() = default;
|
Level::~Level() = default;
|
||||||
|
|
||||||
void Level::loadMatrix(int32_t x, int32_t z, uint32_t radius) {
|
|
||||||
chunks->setCenter(x, z);
|
|
||||||
uint32_t diameter = std::min(
|
|
||||||
radius * 2LL,
|
|
||||||
(settings.chunks.loadDistance.get() + settings.chunks.padding.get()) *
|
|
||||||
2LL
|
|
||||||
);
|
|
||||||
if (chunks->getWidth() != diameter) {
|
|
||||||
chunks->resize(diameter, diameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
World* Level::getWorld() {
|
World* Level::getWorld() {
|
||||||
return world.get();
|
return world.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,11 +9,9 @@
|
|||||||
|
|
||||||
class Content;
|
class Content;
|
||||||
class World;
|
class World;
|
||||||
class Chunks;
|
|
||||||
class Entities;
|
class Entities;
|
||||||
class Inventories;
|
class Inventories;
|
||||||
class LevelEvents;
|
class LevelEvents;
|
||||||
class Lighting;
|
|
||||||
class PhysicsSolver;
|
class PhysicsSolver;
|
||||||
class GlobalChunks;
|
class GlobalChunks;
|
||||||
class Camera;
|
class Camera;
|
||||||
@ -27,7 +25,6 @@ class Level {
|
|||||||
public:
|
public:
|
||||||
const Content* const content;
|
const Content* const content;
|
||||||
|
|
||||||
std::unique_ptr<Chunks> chunks;
|
|
||||||
std::unique_ptr<GlobalChunks> chunksStorage;
|
std::unique_ptr<GlobalChunks> chunksStorage;
|
||||||
std::unique_ptr<Inventories> inventories;
|
std::unique_ptr<Inventories> inventories;
|
||||||
|
|
||||||
@ -44,8 +41,6 @@ public:
|
|||||||
);
|
);
|
||||||
~Level();
|
~Level();
|
||||||
|
|
||||||
void loadMatrix(int32_t x, int32_t z, uint32_t radius);
|
|
||||||
|
|
||||||
World* getWorld();
|
World* getWorld();
|
||||||
|
|
||||||
const World* getWorld() const;
|
const World* getWorld() const;
|
||||||
|
|||||||
@ -10,11 +10,12 @@
|
|||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/GlobalChunks.hpp"
|
#include "voxels/GlobalChunks.hpp"
|
||||||
#include "voxels/VoxelsVolume.hpp"
|
#include "voxels/VoxelsVolume.hpp"
|
||||||
|
#include "voxels/blocks_agent.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "core_defs.hpp"
|
#include "core_defs.hpp"
|
||||||
|
|
||||||
std::unique_ptr<VoxelFragment> VoxelFragment::create(
|
std::unique_ptr<VoxelFragment> VoxelFragment::create(
|
||||||
Level* level,
|
const Level& level,
|
||||||
const glm::ivec3& a,
|
const glm::ivec3& a,
|
||||||
const glm::ivec3& b,
|
const glm::ivec3& b,
|
||||||
bool crop,
|
bool crop,
|
||||||
@ -26,7 +27,7 @@ std::unique_ptr<VoxelFragment> VoxelFragment::create(
|
|||||||
if (crop) {
|
if (crop) {
|
||||||
VoxelsVolume volume(size.x, size.y, size.z);
|
VoxelsVolume volume(size.x, size.y, size.z);
|
||||||
volume.setPosition(start.x, start.y, start.z);
|
volume.setPosition(start.x, start.y, start.z);
|
||||||
level->chunks->getVoxels(&volume);
|
blocks_agent::get_voxels(*level.chunksStorage, &volume);
|
||||||
|
|
||||||
auto end = start + size;
|
auto end = start + size;
|
||||||
|
|
||||||
@ -51,14 +52,14 @@ std::unique_ptr<VoxelFragment> VoxelFragment::create(
|
|||||||
|
|
||||||
VoxelsVolume volume(size.x, size.y, size.z);
|
VoxelsVolume volume(size.x, size.y, size.z);
|
||||||
volume.setPosition(start.x, start.y, start.z);
|
volume.setPosition(start.x, start.y, start.z);
|
||||||
level->chunks->getVoxels(&volume);
|
blocks_agent::get_voxels(*level.chunksStorage, &volume);
|
||||||
|
|
||||||
auto volVoxels = volume.getVoxels();
|
auto volVoxels = volume.getVoxels();
|
||||||
std::vector<voxel> voxels(size.x * size.y * size.z);
|
std::vector<voxel> voxels(size.x * size.y * size.z);
|
||||||
|
|
||||||
std::vector<std::string> blockNames {CORE_AIR};
|
std::vector<std::string> blockNames {CORE_AIR};
|
||||||
std::unordered_map<blockid_t, blockid_t> blocksRegistered {{0, 0}};
|
std::unordered_map<blockid_t, blockid_t> blocksRegistered {{0, 0}};
|
||||||
auto contentIndices = level->content->getIndices();
|
auto contentIndices = level.content->getIndices();
|
||||||
for (size_t i = 0 ; i < voxels.size(); i++) {
|
for (size_t i = 0 ; i < voxels.size(); i++) {
|
||||||
blockid_t id = volVoxels[i].id;
|
blockid_t id = volVoxels[i].id;
|
||||||
blockid_t index;
|
blockid_t index;
|
||||||
@ -170,7 +171,7 @@ void VoxelFragment::prepare(const Content& content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VoxelFragment::place(
|
void VoxelFragment::place(
|
||||||
Chunks& chunks, const glm::ivec3& offset, ubyte rotation
|
GlobalChunks& chunks, const glm::ivec3& offset, ubyte rotation
|
||||||
) {
|
) {
|
||||||
auto& structVoxels = getRuntimeVoxels();
|
auto& structVoxels = getRuntimeVoxels();
|
||||||
for (int y = 0; y < size.y; y++) {
|
for (int y = 0; y < size.y; y++) {
|
||||||
@ -185,7 +186,9 @@ void VoxelFragment::place(
|
|||||||
const auto& structVoxel =
|
const auto& structVoxel =
|
||||||
structVoxels[vox_index(x, y, z, size.x, size.z)];
|
structVoxels[vox_index(x, y, z, size.x, size.z)];
|
||||||
if (structVoxel.id) {
|
if (structVoxel.id) {
|
||||||
chunks.set(sx, sy, sz, structVoxel.id, structVoxel.state);
|
blocks_agent::set(
|
||||||
|
chunks, sx, sy, sz, structVoxel.id, structVoxel.state
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ inline constexpr int STRUCTURE_FORMAT_VERSION = 1;
|
|||||||
|
|
||||||
class Level;
|
class Level;
|
||||||
class Content;
|
class Content;
|
||||||
class Chunks;
|
class GlobalChunks;
|
||||||
|
|
||||||
class VoxelFragment : public Serializable {
|
class VoxelFragment : public Serializable {
|
||||||
glm::ivec3 size;
|
glm::ivec3 size;
|
||||||
@ -45,13 +45,13 @@ public:
|
|||||||
/// @brief Place fragment to the world
|
/// @brief Place fragment to the world
|
||||||
/// @param offset target location
|
/// @param offset target location
|
||||||
/// @param rotation rotation index
|
/// @param rotation rotation index
|
||||||
void place(Chunks& chunks, const glm::ivec3& offset, ubyte rotation);
|
void place(GlobalChunks& chunks, const glm::ivec3& offset, ubyte rotation);
|
||||||
|
|
||||||
/// @brief Create structure copy rotated 90 deg. clockwise
|
/// @brief Create structure copy rotated 90 deg. clockwise
|
||||||
std::unique_ptr<VoxelFragment> rotated(const Content& content) const;
|
std::unique_ptr<VoxelFragment> rotated(const Content& content) const;
|
||||||
|
|
||||||
static std::unique_ptr<VoxelFragment> create(
|
static std::unique_ptr<VoxelFragment> create(
|
||||||
Level* level,
|
const Level& level,
|
||||||
const glm::ivec3& a,
|
const glm::ivec3& a,
|
||||||
const glm::ivec3& b,
|
const glm::ivec3& b,
|
||||||
bool crop,
|
bool crop,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user