Many improvements with lighting, gfx, and stability
- Add curvature shader effect to blocks (not entities yetTM) - Make fromStr with an empty string return Air instead of Invalid - Make the player start with an empty hand instead of with stone - Update chunks on lighting changes! - Fix dirty chunk rendering! - Fix segfault when getting non-existent inventory list.master
parent
49b45d1b9e
commit
b50732ec5e
|
@ -92,12 +92,15 @@ void main() {
|
|||
}
|
||||
|
||||
|
||||
float sunlightIntensity = aLight.w * clamp(sin(time * 10.5) + 0.25, 0, 1) / MAX_SUNLIGHT;
|
||||
float sunlightIntensity = 1;
|
||||
// float sunlightIntensity = aLight.w * clamp(sin(time / 2.5) + 0.25, 0, 1) / MAX_SUNLIGHT;
|
||||
vec3 blockLightColor = (aLight.xyz / MAX_BLOCKLIGHT) * vec3(1 + sunlightIntensity / 4);
|
||||
vec3 sunlightColor = clamp(sunlightIntensity * 1.25 * vec3(1, 0.8, 0.9), 0, 1);
|
||||
vec3 sunlightColor = clamp(sunlightIntensity * 1.25 * vec3(1, 0.9, 0.75), 0, 1);
|
||||
vec3 resultantLight = vec3(max(sunlightColor.x, blockLightColor.x), max(sunlightColor.y, blockLightColor.y), max(sunlightColor.z, blockLightColor.z));
|
||||
|
||||
vec4 worldPos = model * pos;
|
||||
// worldPos.y -= pow(length(view * worldPos * 0.125) - 0.125, 2);
|
||||
worldPos.y -= pow(length(view * worldPos * 0.025) - 0, 2);
|
||||
|
||||
fragPos = (view * worldPos).xyz;
|
||||
texCoords = aTexCoords;
|
||||
|
|
|
@ -14,6 +14,7 @@ ItemDef& DefinitionAtlas::fromId(unsigned int id) const {
|
|||
}
|
||||
|
||||
ItemDef &DefinitionAtlas::fromStr(const std::string& identifier) const {
|
||||
if (identifier == "") return *defs.at(AIR);
|
||||
if (defTable.count(identifier) <= 0) {
|
||||
std::cout << Log::err << "Undefined identifier \"" << identifier << "\" requested, returning invalid." << Log::endl;
|
||||
return *defs.at(INVALID);
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
LocalDefinitionAtlas::LocalDefinitionAtlas(TextureAtlas& atlas) {
|
||||
//Invalid Node
|
||||
BlockModel invalidModel = BlockModel::createCube({atlas["_missing"]}, {}, {});
|
||||
BlockDef* invalid = new BlockDef("invalid", "Invalid (you broke the game!)", 1, invalidModel, invalidModel, true, {}, {{}}, {{}});
|
||||
BlockDef* invalid = new BlockDef("invalid", "Invalid (you broke the game!)", 64, invalidModel, invalidModel, true, {}, {{}}, {{}});
|
||||
defs.push_back(invalid);
|
||||
defTable.insert({"invalid", 0});
|
||||
|
||||
//Air Node
|
||||
BlockModel nullModel {};
|
||||
BlockDef* air = new BlockDef("air", "Air", 1, nullModel, nullModel, false, {}, {}, {});
|
||||
BlockDef* air = new BlockDef("air", "Air", 64, nullModel, nullModel, false, {}, {}, {}, 1);
|
||||
defs.push_back(air);
|
||||
defTable.insert({"air", 1});
|
||||
}
|
||||
|
|
|
@ -6,6 +6,24 @@
|
|||
|
||||
#include "../../lua/api/class/LuaItemStack.h"
|
||||
|
||||
InventoryList::InventoryList(DefinitionAtlas &defs) : defs(defs) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
InventoryList::InventoryList(DefinitionAtlas &defs, const std::string &invName, const std::string &listName,
|
||||
unsigned short size, unsigned short width) :
|
||||
listName(listName),
|
||||
itemstacks(size),
|
||||
invName(invName),
|
||||
width(width),
|
||||
defs(defs) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void InventoryList::initialize() {
|
||||
for (unsigned int i = 0; i < itemstacks.size(); i++) itemstacks[i] = {};
|
||||
}
|
||||
|
||||
unsigned short InventoryList::getLength() const {
|
||||
return itemstacks.size();
|
||||
}
|
||||
|
@ -38,7 +56,7 @@ ItemStack InventoryList::placeStack(unsigned short i, const ItemStack &stack, bo
|
|||
sol::function on_take = luaCallbacks[static_cast<int>(Callback::ON_TAKE)];
|
||||
|
||||
if (stack.count == 0) {
|
||||
if (allowedTake == otherStack.count) setStack(i, {});
|
||||
if (allowedTake == otherStack.count) setStack(i, {DefinitionAtlas::AIR, 0});
|
||||
else setStack(i, {otherStack.id, static_cast<unsigned short>(otherStack.count - allowedTake)});
|
||||
if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
|
||||
return {otherStack.id, allowedTake};
|
||||
|
@ -192,7 +210,7 @@ ItemStack InventoryList::takeStack(ItemStack request, bool playerInitiated) {
|
|||
ItemStack InventoryList::removeStack(unsigned short ind, unsigned short count) {
|
||||
auto stack = getStack(ind);
|
||||
if (count >= stack.count) {
|
||||
setStack(ind, {0, 0});
|
||||
setStack(ind, {DefinitionAtlas::AIR, 0});
|
||||
return stack;
|
||||
}
|
||||
else {
|
||||
|
@ -244,4 +262,4 @@ void InventoryList::setLuaCallback(InventoryList::Callback type, sol::function c
|
|||
|
||||
sol::function InventoryList::getLuaCallback(InventoryList::Callback type) {
|
||||
return luaCallbacks[static_cast<size_t>(type)];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,8 @@ public:
|
|||
ON_PUT
|
||||
};
|
||||
|
||||
InventoryList(DefinitionAtlas& defs) : defs(defs) {};
|
||||
InventoryList(DefinitionAtlas& defs, const std::string& invName, const std::string& listName, unsigned short size, unsigned short width) :
|
||||
defs(defs), invName(invName), listName(listName), width(width), itemstacks(size) {};
|
||||
InventoryList(DefinitionAtlas& defs);
|
||||
InventoryList(DefinitionAtlas& defs, const std::string& invName, const std::string& listName, unsigned short size, unsigned short width);
|
||||
|
||||
unsigned short getLength() const;
|
||||
unsigned short getWidth() const;
|
||||
|
@ -54,6 +53,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void manipulated() = 0;
|
||||
void initialize();
|
||||
|
||||
std::string invName {}, listName {};
|
||||
unsigned short width = 0;
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
#include "../../lua/api/class/LuaItemStack.h"
|
||||
|
||||
ItemStack::ItemStack(LuaItemStack &stack, const DefinitionAtlas &atlas) :
|
||||
id((stack.get_count() == 0) ? 0 : atlas.fromStr(stack.get_name()).index),
|
||||
count((this->id == 0) ? 0 : stack.get_count()) {}
|
||||
id((stack.get_count() == 0) ? DefinitionAtlas::AIR : atlas.fromStr(stack.get_name()).index),
|
||||
count((this->id == DefinitionAtlas::AIR) ? 0 : stack.get_count()) {}
|
||||
|
||||
ItemStack::ItemStack(unsigned int id, unsigned short count) :
|
||||
id((count == 0) ? 0 : id),
|
||||
count((this->id == 0) ? 0 : count) {}
|
||||
id((count == 0) ? DefinitionAtlas::AIR : id),
|
||||
count((this->id == DefinitionAtlas::AIR) ? 0 : count) {}
|
||||
|
||||
bool ItemStack::operator!=(const ItemStack &b) const {
|
||||
return (b.count != this->count || b.id != this->id);
|
||||
|
|
|
@ -18,6 +18,6 @@ public:
|
|||
bool operator!=(const ItemStack& b) const;
|
||||
bool operator==(const ItemStack& b) const;
|
||||
|
||||
unsigned int id = 0;
|
||||
unsigned int id = DefinitionAtlas::AIR;
|
||||
unsigned short count = 0;
|
||||
};
|
|
@ -14,11 +14,10 @@
|
|||
|
||||
ServerInventoryList::ServerInventoryList(DefinitionAtlas& defs, ClientList* list,
|
||||
const std::string& invName, const std::string& listName, unsigned short size, unsigned short width) :
|
||||
|
||||
InventoryList(defs, invName, listName, size, width),
|
||||
clients(list) {}
|
||||
|
||||
void ServerInventoryList::manipulated(){
|
||||
void ServerInventoryList::manipulated() {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,27 +7,23 @@
|
|||
#include "../../../util/Ray.h"
|
||||
|
||||
Player::Player(LocalWorld& world, ClientGame& defs, Renderer& renderer, LocalInventoryRefs& refs) :
|
||||
Collidable(world, defs, {{-0.3, 0, -0.3}, {0.3, 1.8, 0.3}}),
|
||||
Collidable(world, defs, {{-0.3, 0, -0.3}, {0.3, 1.8, 0.3}}),
|
||||
|
||||
refs(refs),
|
||||
defs(defs),
|
||||
renderer(renderer),
|
||||
wireframe({}, 0.01, {1, 1, 1}),
|
||||
gameGui(refs, renderer.window.getSize(), defs, renderer) {}
|
||||
|
||||
void Player::update(Input &input, double delta, glm::vec2 mouseDelta) {
|
||||
if (activeBlock == -1) {
|
||||
activeBlock = defs.defs.fromStr("zeus:default:stone").index;
|
||||
handItemModel.setModel(defs.defs.fromId(activeBlock).entityModel);
|
||||
handItemModel.parent = &handModel;
|
||||
}
|
||||
handItemModel.setVisible(gameGui.isVisible());
|
||||
|
||||
gameGui.update(delta);
|
||||
refs(refs),
|
||||
game(defs),
|
||||
renderer(renderer),
|
||||
wireframe({}, 0.01, {1, 1, 1}),
|
||||
gameGui(refs, renderer.window.getSize(), defs, renderer) {
|
||||
handItemModel.parent = &handModel;
|
||||
|
||||
renderer.window.addResizeCallback("player", [&](glm::ivec2 win) {
|
||||
gameGui.winResized(win);
|
||||
});
|
||||
}
|
||||
|
||||
void Player::update(Input &input, double delta, glm::vec2 mouseDelta) {
|
||||
gameGui.update(delta);
|
||||
handItemModel.setVisible(gameGui.isVisible());
|
||||
|
||||
moveAndLook(input, delta, mouseDelta);
|
||||
findPointedThing(input);
|
||||
|
@ -108,7 +104,7 @@ void Player::updateCamera() {
|
|||
renderer.camera.setYaw(yaw);
|
||||
renderer.camera.setPitch(pitch);
|
||||
|
||||
auto type = defs.defs.fromId(activeBlock).type;
|
||||
auto type = game.defs.fromId(activeBlock).type;
|
||||
|
||||
glm::vec3 eyesPos = {pos.x, pos.y + EYE_HEIGHT, pos.z};
|
||||
renderer.camera.setPos(eyesPos);
|
||||
|
@ -159,7 +155,7 @@ void Player::findPointedThing(Input &input) {
|
|||
if (blockChunk == nullptr) continue;
|
||||
|
||||
unsigned int blockID = blockChunk->getBlock(Space::Block::relative::toChunk(roundedPos));
|
||||
auto& boxes = defs.defs.blockFromId(blockID).sBoxes;
|
||||
auto& boxes = game.defs.blockFromId(blockID).sBoxes;
|
||||
|
||||
for (auto& sBox : boxes) {
|
||||
auto face = sBox.intersects(rayEnd, roundedPos);
|
||||
|
@ -181,7 +177,7 @@ void Player::updateWireframe() {
|
|||
wireframe.setVisible(false);
|
||||
}
|
||||
else if (pointedThing.thing == PointedThing::Thing::BLOCK) {
|
||||
auto& boxes = defs.defs.blockFromId(pointedThing.target.block.blockId).sBoxes;
|
||||
auto& boxes = game.defs.blockFromId(pointedThing.target.block.blockId).sBoxes;
|
||||
float distance = glm::distance(pos, glm::vec3(pointedThing.target.block.pos) + glm::vec3(0.5));
|
||||
|
||||
wireframe.updateMesh(boxes, 0.002f + distance * 0.0014f);
|
||||
|
@ -207,7 +203,7 @@ void Player::breakBlock(Input& input, double delta) {
|
|||
if (breakInterval > BLOCK_INTERVAL) breakInterval = 0;
|
||||
}
|
||||
|
||||
if (input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) {
|
||||
if (input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT) && activeBlock != DefinitionAtlas::AIR) {
|
||||
world.localSetBlock(pointedThing.target.block.pos + SelectionBox::faceToOffset(pointedThing.target.block.face), activeBlock);
|
||||
}
|
||||
}
|
||||
|
@ -272,8 +268,8 @@ LocalInventory& Player::getInventory() {
|
|||
*/
|
||||
|
||||
void Player::setActiveBlock(const std::string& block) {
|
||||
activeBlock = defs.defs.fromStr(block).index;
|
||||
handItemModel.setModel(defs.defs.fromId(activeBlock).entityModel);
|
||||
activeBlock = game.defs.fromStr(block).index;
|
||||
handItemModel.setModel(game.defs.fromId(activeBlock).entityModel);
|
||||
}
|
||||
|
||||
void Player::showMenu(std::shared_ptr<LuaGuiElement> root) {
|
||||
|
|
|
@ -65,7 +65,7 @@ private:
|
|||
void updateWireframe();
|
||||
void breakBlock(Input& input, double delta);
|
||||
|
||||
ClientGame& defs;
|
||||
ClientGame& game;
|
||||
Renderer& renderer;
|
||||
LocalInventoryRefs& refs;
|
||||
|
||||
|
@ -78,7 +78,7 @@ private:
|
|||
float pitch = 0;
|
||||
bool flying = false;
|
||||
|
||||
unsigned int activeBlock = -1;
|
||||
unsigned int activeBlock = DefinitionAtlas::AIR;
|
||||
PointedThing pointedThing;
|
||||
double breakInterval = 0;
|
||||
};
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "LocalLuaInventory.h"
|
||||
|
||||
LocalLuaInventoryList LocalLuaInventory::get_list(std::string name) {
|
||||
return LocalLuaInventoryList(*inventory[name]);
|
||||
sol::object LocalLuaInventory::get_list(sol::this_state s, std::string name) {
|
||||
auto inv = inventory[name];
|
||||
if (!inv) return sol::nil;
|
||||
return sol::make_object<LocalLuaInventoryList>(s, LocalLuaInventoryList(*inv));
|
||||
}
|
|
@ -15,6 +15,6 @@ public:
|
|||
DefinitionAtlas& defs;
|
||||
|
||||
// LocalLuaInventoryList add_list(std::string name, int size, int width);
|
||||
LocalLuaInventoryList get_list(std::string name);
|
||||
sol::object get_list(sol::this_state s, std::string name);
|
||||
// void remove_list(std::string name);
|
||||
};
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
|
||||
#include "ServerLuaInventory.h"
|
||||
|
||||
ServerLuaInventoryList ServerLuaInventory::add_list(std::string name, int size, int width) {
|
||||
sol::object ServerLuaInventory::add_list(sol::this_state s, std::string name, int size, int width) {
|
||||
inventory.createList(name, size, width);
|
||||
return ServerLuaInventoryList(*inventory[name]);
|
||||
return sol::make_object<ServerLuaInventoryList>(s, ServerLuaInventoryList(*inventory[name]));
|
||||
}
|
||||
|
||||
ServerLuaInventoryList ServerLuaInventory::get_list(std::string name) {
|
||||
return ServerLuaInventoryList(*inventory[name]);
|
||||
sol::object ServerLuaInventory::get_list(sol::this_state s, std::string name) {
|
||||
auto inv = inventory[name];
|
||||
if (!inv) return sol::nil;
|
||||
return sol::make_object<ServerLuaInventoryList>(s, ServerLuaInventoryList(*inv));
|
||||
}
|
||||
|
||||
void ServerLuaInventory::remove_list(std::string name) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../../game/inventory/Inventory.h"
|
||||
|
||||
#include "ServerLuaInventoryList.h"
|
||||
|
||||
class ServerLuaInventory {
|
||||
|
@ -14,7 +15,7 @@ public:
|
|||
Inventory& inventory;
|
||||
DefinitionAtlas& defs;
|
||||
|
||||
ServerLuaInventoryList add_list(std::string name, int size, int width);
|
||||
ServerLuaInventoryList get_list(std::string name);
|
||||
sol::object add_list(sol::this_state s, std::string name, int size, int width);
|
||||
sol::object get_list(sol::this_state s, std::string name);
|
||||
void remove_list(std::string name);
|
||||
};
|
||||
|
|
|
@ -16,19 +16,33 @@ ServerWorld::ServerWorld(unsigned int seed, ServerGame& game, ClientList& client
|
|||
seed(seed),
|
||||
game(game) {
|
||||
|
||||
//Pregenerate chunk generation order
|
||||
generateOrder.reserve(MB_GEN_H * 2 * MB_GEN_H * 2 * MB_GEN_V * 2);
|
||||
generateOrder.reserve(MB_GEN_H * 2 + 1 * MB_GEN_H * 2 + 1 * MB_GEN_V * 2 + 1);
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> found {};
|
||||
std::queue<glm::ivec3> queue {};
|
||||
|
||||
for (int i = 0; i <= MB_GEN_H; i++) {
|
||||
for (int j = 0; j <= i; j++) {
|
||||
for (int k = -MB_GEN_V; k <= MB_GEN_V; k++) {
|
||||
for (int l = -1; l <= 1; l += 2) {
|
||||
for (int m = -1; m <= 1; m += 2) {
|
||||
for (int n = 0; n <= 1; n++) {
|
||||
generateOrder.emplace_back((n ? l*i : m*j), k, (n ? m*j : l*i));
|
||||
}
|
||||
}
|
||||
}
|
||||
queue.emplace(0, 0, 0);
|
||||
found.emplace(0, 0, 0);
|
||||
|
||||
const std::vector<glm::ivec3> dirs {
|
||||
glm::ivec3 {1, 0, 0}, glm::ivec3 {-1, 0, 0},
|
||||
glm::ivec3 {0, 1, 0}, glm::ivec3 {0, -1, 0},
|
||||
glm::ivec3 {0, 0, 1}, glm::ivec3 {0, 0, -1}};
|
||||
|
||||
while (!queue.empty()) {
|
||||
glm::ivec3 pos = queue.front();
|
||||
queue.pop();
|
||||
|
||||
generateOrder.push_back(pos);
|
||||
|
||||
for (auto dir : dirs) {
|
||||
glm::ivec3 offset = pos + dir;
|
||||
if (offset.x < -MB_GEN_H || offset.x > MB_GEN_H ||
|
||||
offset.y < -MB_GEN_V || offset.y > MB_GEN_V ||
|
||||
offset.z < -MB_GEN_H || offset.z > MB_GEN_H ||
|
||||
found.count(offset)) continue;
|
||||
else {
|
||||
found.insert(offset);
|
||||
queue.push(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace Space {
|
|||
}
|
||||
|
||||
namespace world {
|
||||
// Get a Chunk engine position from a Block's world position.
|
||||
// Get a Chunk world position from a Block's world position.
|
||||
static inline glm::ivec3 fromBlock(const glm::ivec3& pos) {
|
||||
return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH);
|
||||
}
|
||||
|
|
|
@ -105,10 +105,7 @@ void Dimension::addLight(glm::ivec3 pos, glm::ivec3 light) {
|
|||
lightAddQueue[0].emplace(index, startChunk.get());
|
||||
lightAddQueue[1].emplace(index, startChunk.get());
|
||||
lightAddQueue[2].emplace(index, startChunk.get());
|
||||
|
||||
propogateAddNodes(0);
|
||||
propogateAddNodes(1);
|
||||
propogateAddNodes(2);
|
||||
propogateAddNodes();
|
||||
}
|
||||
|
||||
void Dimension::removeLight(glm::ivec3 pos) {
|
||||
|
@ -116,64 +113,84 @@ void Dimension::removeLight(glm::ivec3 pos) {
|
|||
glm::ivec3 val = startChunk->getBlockLight(Space::Block::index(pos));
|
||||
|
||||
startChunk->setBlockLight(Space::Block::index(pos), {});
|
||||
lightRemoveQueue[0].emplace(Space::Block::index(pos), val.r, startChunk.get());
|
||||
lightRemoveQueue[1].emplace(Space::Block::index(pos), val.g, startChunk.get());
|
||||
lightRemoveQueue[2].emplace(Space::Block::index(pos), val.b, startChunk.get());
|
||||
|
||||
propogateRemoveNodes(0);
|
||||
propogateRemoveNodes(1);
|
||||
propogateRemoveNodes(2);
|
||||
lightRemoveQueue[0].emplace(Space::Block::index(pos), val.x, startChunk.get());
|
||||
lightRemoveQueue[1].emplace(Space::Block::index(pos), val.y, startChunk.get());
|
||||
lightRemoveQueue[2].emplace(Space::Block::index(pos), val.z, startChunk.get());
|
||||
propogateRemoveNodes();
|
||||
}
|
||||
|
||||
void Dimension::propogateAddNodes(unsigned char channel) {
|
||||
while (!lightAddQueue[channel].empty()) {
|
||||
LightAddNode& node = lightAddQueue[channel].front();
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
||||
|
||||
unsigned char lightLevel = node.chunk->getBlockLight(node.index, channel);
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
for (unsigned int channel = 0; channel < 3; channel++) {
|
||||
while (!lightAddQueue[channel].empty()) {
|
||||
LightAddNode& node = lightAddQueue[channel].front();
|
||||
|
||||
const static std::array<glm::ivec3, 6> checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} };
|
||||
for (const auto& i : checks) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
if (!defs.blockFromId(getBlock(check)).solid && getBlockLight(check, node.chunk)[channel] + 2 <= lightLevel) {
|
||||
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
chunk->setBlockLight(Space::Block::index(check), channel, lightLevel - 1);
|
||||
lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
unsigned char lightLevel = node.chunk->getBlockLight(node.index, channel);
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
const static std::array<glm::ivec3, 6> checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} };
|
||||
for (const auto& i : checks) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
if (!defs.blockFromId(getBlock(check)).solid && getBlockLight(check, node.chunk)[channel] + 2 <= lightLevel) {
|
||||
BlockChunk* chunk;
|
||||
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
|
||||
else {
|
||||
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
chunksUpdated.insert(chunk->pos);
|
||||
chunk->dirty = true;
|
||||
}
|
||||
chunk->setBlockLight(Space::Block::index(check), channel, lightLevel - 1);
|
||||
lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
}
|
||||
}
|
||||
lightAddQueue[channel].pop();
|
||||
}
|
||||
lightAddQueue[channel].pop();
|
||||
}
|
||||
}
|
||||
|
||||
void Dimension::propogateRemoveNodes(unsigned char channel) {
|
||||
while (!lightRemoveQueue[channel].empty()) {
|
||||
LightRemoveNode& node = lightRemoveQueue[channel].front();
|
||||
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
const static std::array<glm::ivec3, 6> checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} };
|
||||
for (const auto& i : checks) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
unsigned char checkLight = getBlockLight(check, node.chunk)[channel];
|
||||
|
||||
if (checkLight != 0 && checkLight < node.value) {
|
||||
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
|
||||
auto blockLight = defs.blockFromId(chunk->getBlock(Space::Block::index(check))).lightSource[channel];
|
||||
chunk->setBlockLight(Space::Block::index(check), channel, blockLight);
|
||||
if (blockLight) lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
lightRemoveQueue[channel].emplace(Space::Block::index(check), checkLight, chunk);
|
||||
}
|
||||
else if (checkLight >= node.value) {
|
||||
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
}
|
||||
}
|
||||
lightRemoveQueue[channel].pop();
|
||||
}
|
||||
|
||||
propogateAddNodes(channel);
|
||||
return chunksUpdated;
|
||||
}
|
||||
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
||||
|
||||
for (unsigned int channel = 0; channel < 3; channel++) {
|
||||
while (!lightRemoveQueue[channel].empty()) {
|
||||
LightRemoveNode& node = lightRemoveQueue[channel].front();
|
||||
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
const static std::array<glm::ivec3, 6> checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} };
|
||||
for (const auto& i : checks) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
unsigned char checkLight = getBlockLight(check, node.chunk)[channel];
|
||||
|
||||
if (checkLight != 0 && checkLight < node.value) {
|
||||
BlockChunk* chunk;
|
||||
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
|
||||
else {
|
||||
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
chunksUpdated.insert(chunk->pos);
|
||||
chunk->dirty = true;
|
||||
}
|
||||
|
||||
auto blockLight = defs.blockFromId(chunk->getBlock(Space::Block::index(check))).lightSource[channel];
|
||||
chunk->setBlockLight(Space::Block::index(check), channel, blockLight);
|
||||
if (blockLight) lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
lightRemoveQueue[channel].emplace(Space::Block::index(check), checkLight, chunk);
|
||||
}
|
||||
else if (checkLight >= node.value) {
|
||||
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
}
|
||||
}
|
||||
lightRemoveQueue[channel].pop();
|
||||
}
|
||||
}
|
||||
|
||||
propogateAddNodes();
|
||||
return chunksUpdated;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <queue>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "../util/Vec.h"
|
||||
#include "region/Region.h"
|
||||
|
@ -33,6 +34,8 @@ protected:
|
|||
block_region_map regions;
|
||||
DefinitionAtlas& defs;
|
||||
|
||||
virtual std::unordered_set<glm::ivec3, Vec::ivec3> propogateAddNodes();
|
||||
virtual std::unordered_set<glm::ivec3, Vec::ivec3> propogateRemoveNodes();
|
||||
private:
|
||||
inline std::shared_ptr<Region> getOrCreateRegion(glm::ivec3 pos);
|
||||
inline std::shared_ptr<MapBlock> getOrCreateMapBlock(glm::ivec3 mapBlockPosition);
|
||||
|
@ -43,9 +46,6 @@ private:
|
|||
inline void addLight(glm::ivec3 pos, glm::ivec3 light);
|
||||
inline void removeLight(glm::ivec3 pos);
|
||||
|
||||
void propogateAddNodes(unsigned char channel);
|
||||
void propogateRemoveNodes(unsigned char channel);
|
||||
|
||||
struct LightAddNode {
|
||||
LightAddNode(unsigned short index, BlockChunk* chunk) : index(index), chunk(chunk) {};
|
||||
unsigned short index;
|
||||
|
|
|
@ -216,28 +216,37 @@ bool LocalDimension::setBlock(glm::ivec3 pos, unsigned int block) {
|
|||
auto chunk = getChunk(chunkPos);
|
||||
|
||||
chunk->dirty = true;
|
||||
|
||||
auto lp = Space::Block::relative::toChunk(pos);
|
||||
auto cp = Space::Chunk::world::fromBlock(pos);
|
||||
|
||||
if (lp.x == 15 && getChunk(cp + glm::ivec3 {1, 0, 0})) getChunk(cp + glm::ivec3 {1, 0, 0})->dirty = true;
|
||||
else if (lp.x == 0 && getChunk(cp + glm::ivec3 {-1, 0, 0})) getChunk(cp + glm::ivec3 {-1, 0, 0})->dirty = true;
|
||||
if (lp.y == 15 && getChunk(cp + glm::ivec3 {0, 1, 0})) getChunk(cp + glm::ivec3 {0, 1, 0})->dirty = true;
|
||||
else if (lp.y == 0 && getChunk(cp + glm::ivec3 {0, -1, 0})) getChunk(cp + glm::ivec3 {0, -1, 0})->dirty = true;
|
||||
if (lp.z == 15 && getChunk(cp + glm::ivec3 {0, 0, 1})) getChunk(cp + glm::ivec3 {0, 0, 1})->dirty = true;
|
||||
else if (lp.z == 0 && getChunk(cp + glm::ivec3 {0, 0, -1})) getChunk(cp + glm::ivec3 {0, 0, -1})->dirty = true;
|
||||
|
||||
attemptMeshChunk(chunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LocalDimension::attemptMeshChunk(const std::shared_ptr<BlockChunk>& chunk, bool updateAdjacents) {
|
||||
// if (!chunk->dirty) return; //TODO
|
||||
auto dirs = Vec::cardinalVectors;
|
||||
bool allExists = true;
|
||||
for (auto dir : dirs) {
|
||||
if (!getAdjacentExists(chunk->pos + dir, updateAdjacents)) {
|
||||
allExists = false;
|
||||
}
|
||||
}
|
||||
static const std::vector<glm::ivec3> dirs {
|
||||
glm::ivec3 {1, 0, 0}, glm::ivec3 {-1, 0, 0},
|
||||
glm::ivec3 {0, 1, 0}, glm::ivec3 {0, -1, 0},
|
||||
glm::ivec3 {0, 0, 1}, glm::ivec3 {0, 0, -1}};
|
||||
|
||||
if (allExists) {
|
||||
if (chunk->shouldHaveMesh) {
|
||||
pendingMesh.push_back(chunk->pos);
|
||||
}
|
||||
else removeMeshChunk(chunk->pos);
|
||||
bool renderable = true;
|
||||
for (auto dir : dirs) if (!getAdjacentExists(chunk->pos + dir, updateAdjacents)) renderable = false;
|
||||
if (!renderable) return;
|
||||
|
||||
chunk->dirty = false; //TODO: Make dirty work
|
||||
}
|
||||
if (!chunk->dirty) return;
|
||||
if (!chunk->shouldHaveMesh) removeMeshChunk(chunk->pos);
|
||||
|
||||
|
||||
pendingMesh.push_back(chunk->pos);
|
||||
chunk->dirty = false;
|
||||
}
|
||||
|
||||
bool LocalDimension::getAdjacentExists(glm::vec3 pos, bool updateAdjacents) {
|
||||
|
@ -245,4 +254,16 @@ bool LocalDimension::getAdjacentExists(glm::vec3 pos, bool updateAdjacents) {
|
|||
if (chunk == nullptr) return false;
|
||||
if (updateAdjacents) attemptMeshChunk(chunk, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> LocalDimension::propogateAddNodes() {
|
||||
auto updated = Dimension::propogateAddNodes();
|
||||
for (auto& update : updated) attemptMeshChunk(getChunk(update));
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> LocalDimension::propogateRemoveNodes() {
|
||||
auto updated = Dimension::propogateRemoveNodes();
|
||||
for (auto& update : updated) attemptMeshChunk(getChunk(update));
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -40,6 +40,11 @@ public:
|
|||
|
||||
int lastMeshUpdates = 0;
|
||||
std::vector<PlayerEntity> playerEntities;
|
||||
|
||||
protected:
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> propogateAddNodes() override;
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> propogateRemoveNodes() override;
|
||||
|
||||
private:
|
||||
typedef std::list<std::shared_ptr<ChunkRenderElem>>::iterator chunk_ref;
|
||||
typedef std::list<std::shared_ptr<LocalLuaEntity>>::iterator local_ent_ref;
|
||||
|
|
|
@ -120,8 +120,8 @@ inline void BlockChunk::setBlockLight(unsigned int ind, glm::ivec3 l) {
|
|||
}
|
||||
|
||||
inline void BlockChunk::setBlockLight(unsigned int ind, unsigned char channel, unsigned char l){
|
||||
channel == 0 ? light[ind].r = l :
|
||||
channel == 1 ? light[ind].g = l :
|
||||
channel == 0 ? light[ind].r = l:
|
||||
channel == 1 ? light[ind].g = l:
|
||||
light[ind].b = l;
|
||||
}
|
||||
|
||||
|
@ -134,9 +134,9 @@ inline glm::ivec3 BlockChunk::getBlockLight(unsigned int ind) {
|
|||
}
|
||||
|
||||
inline unsigned char BlockChunk::getBlockLight(unsigned int ind, unsigned char channel) {
|
||||
return channel == 0 ? light[ind].r :
|
||||
channel == 1 ? light[ind].g :
|
||||
light[ind].b;
|
||||
return channel == 0 ? light[ind].r:
|
||||
channel == 1 ? light[ind].g:
|
||||
light[ind].b;
|
||||
}
|
||||
|
||||
inline glm::vec4 BlockChunk::getLightVec(unsigned int ind) {
|
||||
|
|
|
@ -40,7 +40,8 @@ local function select_slot(n)
|
|||
for i, list in ipairs(api.lists) do list.visible = i ~= n end
|
||||
for i, label in ipairs(api.labels) do label.visible = i ~= n end
|
||||
|
||||
zepha.player:set_selected_block(zepha.player:get_inventory():get_list("hot_wheel_" .. slot):get_stack(item).name)
|
||||
local inv = zepha.player:get_inventory():get_list("hot_wheel_" .. slot)
|
||||
if inv then zepha.player:set_selected_block(inv:get_stack(item).name) end
|
||||
if not rotating then position() end
|
||||
end
|
||||
|
||||
|
@ -49,9 +50,13 @@ local function select_item(n)
|
|||
local offset = slot - 1
|
||||
api.list_expanded_indicator.position = { 2 + 18 * (item - 1), 0 }
|
||||
|
||||
zepha.player:set_selected_block(zepha.player:get_inventory():get_list("hot_wheel_" .. slot):get_stack(item).name)
|
||||
local inv = zepha.player:get_inventory():get_list("hot_wheel_" .. slot)
|
||||
if inv then zepha.player:set_selected_block(inv:get_stack(item).name) end
|
||||
end
|
||||
|
||||
select_slot(1)
|
||||
select_item(0)
|
||||
|
||||
local function key(n)
|
||||
select_slot(n)
|
||||
end
|
||||
|
|
|
@ -7,5 +7,5 @@ zepha.register_block("zeus:default:cobblestone", {
|
|||
pick = 3
|
||||
},
|
||||
yields = "zeus:default:cobblestone",
|
||||
light_source = { 31, 16, 4 },
|
||||
light_source = { 31, 0, 0 },
|
||||
})
|
|
@ -7,6 +7,6 @@ zepha.register_block("zeus:default:dirt", {
|
|||
shovel = 1,
|
||||
pick = 2
|
||||
},
|
||||
light_source = { 0, 15, 31 },
|
||||
light_source = { 0, 0, 31 },
|
||||
yields = "zeus:default:dirt"
|
||||
})
|
|
@ -1,31 +1,28 @@
|
|||
local noise = {
|
||||
heightmap = {
|
||||
module = "const"
|
||||
module = "add",
|
||||
sources = {{
|
||||
## Elevation
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.002,
|
||||
octaves = 8
|
||||
},
|
||||
scale = 250,
|
||||
bias = -32
|
||||
}, {
|
||||
## Features
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.2,
|
||||
octaves = 3,
|
||||
},
|
||||
scale = 6,
|
||||
bias = 6
|
||||
}}
|
||||
}
|
||||
## heightmap = {
|
||||
## module = "add",
|
||||
## sources = {{
|
||||
## ## Elevation
|
||||
## module = "scale_bias",
|
||||
## source = {
|
||||
## module = "perlin",
|
||||
## frequency = 0.002,
|
||||
## octaves = 8
|
||||
## },
|
||||
## scale = 250,
|
||||
## bias = -32
|
||||
## }, {
|
||||
## ## Features
|
||||
## module = "scale_bias",
|
||||
## source = {
|
||||
## module = "perlin",
|
||||
## frequency = 0.2,
|
||||
## octaves = 3,
|
||||
## },
|
||||
## scale = 6,
|
||||
## bias = 6
|
||||
## }}
|
||||
## }
|
||||
}
|
||||
|
||||
zepha.register_biome("zeus:mapgen:plains", {
|
||||
|
@ -35,7 +32,7 @@ zepha.register_biome("zeus:mapgen:plains", {
|
|||
roughness = 20/100,
|
||||
},
|
||||
blocks = {
|
||||
top = "zeus:default:stone",
|
||||
top = "zeus:default:grass",
|
||||
soil = "zeus:default:dirt",
|
||||
rock = "zeus:default:stone"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue