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
Nicole Collings 2020-05-13 20:43:31 -07:00
parent 49b45d1b9e
commit b50732ec5e
25 changed files with 254 additions and 173 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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});
}

View File

@ -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)];
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
};

View File

@ -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));
}

View File

@ -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);
};

View File

@ -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) {

View File

@ -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);
};

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 {};
}

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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 },
})

View File

@ -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"
})

View File

@ -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"
},