inventory regions, minor refactor
This commit is contained in:
parent
a57fba4fa4
commit
49fdcdfb27
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "base",
|
"id": "base",
|
||||||
"title": "Base",
|
"title": "Base",
|
||||||
"version": "0.18",
|
"version": "0.19",
|
||||||
"description": "basic content package"
|
"description": "basic content package"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,11 @@ static void to_binary(ByteBuilder& builder, const Value* value) {
|
|||||||
static List* array_from_binary(ByteReader& reader);
|
static List* array_from_binary(ByteReader& reader);
|
||||||
static Map* object_from_binary(ByteReader& reader);
|
static Map* object_from_binary(ByteReader& reader);
|
||||||
|
|
||||||
std::vector<ubyte> json::to_binary(const Map* obj) {
|
std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
|
||||||
|
if (compress) {
|
||||||
|
auto bytes = to_binary(obj, false);
|
||||||
|
return gzip::compress(bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
ByteBuilder builder;
|
ByteBuilder builder;
|
||||||
// type byte
|
// type byte
|
||||||
builder.put(BJSON_TYPE_DOCUMENT);
|
builder.put(BJSON_TYPE_DOCUMENT);
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace json {
|
|||||||
const int BJSON_TYPE_NULL = 0xC;
|
const int BJSON_TYPE_NULL = 0xC;
|
||||||
const int BJSON_TYPE_CDOCUMENT = 0x1F;
|
const int BJSON_TYPE_CDOCUMENT = 0x1F;
|
||||||
|
|
||||||
extern std::vector<ubyte> to_binary(const dynamic::Map* obj);
|
extern std::vector<ubyte> to_binary(const dynamic::Map* obj, bool compress=false);
|
||||||
extern std::unique_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
|
extern std::unique_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -121,21 +121,21 @@ void ByteReader::checkMagic(const char* data, size_t size) {
|
|||||||
|
|
||||||
ubyte ByteReader::get() {
|
ubyte ByteReader::get() {
|
||||||
if (pos == size) {
|
if (pos == size) {
|
||||||
throw std::underflow_error("buffer underflow");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
return data[pos++];
|
return data[pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
ubyte ByteReader::peek() {
|
ubyte ByteReader::peek() {
|
||||||
if (pos == size) {
|
if (pos == size) {
|
||||||
throw std::underflow_error("buffer underflow");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
return data[pos];
|
return data[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t ByteReader::getInt16() {
|
int16_t ByteReader::getInt16() {
|
||||||
if (pos+2 > size) {
|
if (pos+2 > size) {
|
||||||
throw std::underflow_error("unexpected end");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
pos += 2;
|
pos += 2;
|
||||||
return (static_cast<int16_t>(data[pos - 1]) << 8) |
|
return (static_cast<int16_t>(data[pos - 1]) << 8) |
|
||||||
@ -144,7 +144,7 @@ int16_t ByteReader::getInt16() {
|
|||||||
|
|
||||||
int32_t ByteReader::getInt32() {
|
int32_t ByteReader::getInt32() {
|
||||||
if (pos+4 > size) {
|
if (pos+4 > size) {
|
||||||
throw std::underflow_error("unexpected end");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
pos += 4;
|
pos += 4;
|
||||||
return (static_cast<int32_t>(data[pos - 1]) << 24) |
|
return (static_cast<int32_t>(data[pos - 1]) << 24) |
|
||||||
@ -155,7 +155,7 @@ int32_t ByteReader::getInt32() {
|
|||||||
|
|
||||||
int64_t ByteReader::getInt64() {
|
int64_t ByteReader::getInt64() {
|
||||||
if (pos+8 > size) {
|
if (pos+8 > size) {
|
||||||
throw std::underflow_error("unexpected end");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
pos += 8;
|
pos += 8;
|
||||||
return (static_cast<int64_t>(data[pos - 1]) << 56) |
|
return (static_cast<int64_t>(data[pos - 1]) << 56) |
|
||||||
@ -191,7 +191,7 @@ const char* ByteReader::getCString() {
|
|||||||
std::string ByteReader::getString() {
|
std::string ByteReader::getString() {
|
||||||
uint32_t length = (uint32_t)getInt32();
|
uint32_t length = (uint32_t)getInt32();
|
||||||
if (pos+length > size) {
|
if (pos+length > size) {
|
||||||
throw std::underflow_error("unexpected end");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
pos += length;
|
pos += length;
|
||||||
return std::string(reinterpret_cast<const char*>(data+pos-length), length);
|
return std::string(reinterpret_cast<const char*>(data+pos-length), length);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
#include "typedefs.h"
|
#include "typedefs.h"
|
||||||
|
|
||||||
const int ENGINE_VERSION_MAJOR = 0;
|
const int ENGINE_VERSION_MAJOR = 0;
|
||||||
const int ENGINE_VERSION_MINOR = 18;
|
const int ENGINE_VERSION_MINOR = 19;
|
||||||
|
|
||||||
const int BLOCK_AIR = 0;
|
const int BLOCK_AIR = 0;
|
||||||
const int ITEM_EMPTY = 0;
|
const int ITEM_EMPTY = 0;
|
||||||
@ -28,7 +28,7 @@ const itemid_t ITEM_VOID = std::numeric_limits<itemid_t>::max();
|
|||||||
|
|
||||||
const blockid_t MAX_BLOCKS = BLOCK_VOID;
|
const blockid_t MAX_BLOCKS = BLOCK_VOID;
|
||||||
|
|
||||||
inline uint vox_index(int x, int y, int z, int w=CHUNK_W, int d=CHUNK_D) {
|
constexpr uint vox_index(uint x, uint y, uint z, uint w=CHUNK_W, uint d=CHUNK_D) {
|
||||||
return (y * d + z) * w + x;
|
return (y * d + z) * w + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -173,6 +173,7 @@ void ContentLoader::loadBlock(Block* def, std::string name, fs::path file) {
|
|||||||
root->num("draw-group", def->drawGroup);
|
root->num("draw-group", def->drawGroup);
|
||||||
root->str("picking-item", def->pickingItem);
|
root->str("picking-item", def->pickingItem);
|
||||||
root->str("script-name", def->scriptName);
|
root->str("script-name", def->scriptName);
|
||||||
|
root->num("inventory-size", def->inventorySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadCustomBlockModel(Block* def, dynamic::Map* primitives) {
|
void ContentLoader::loadCustomBlockModel(Block* def, dynamic::Map* primitives) {
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include "../world/World.h"
|
#include "../world/World.h"
|
||||||
#include "../lighting/Lightmap.h"
|
#include "../lighting/Lightmap.h"
|
||||||
|
|
||||||
|
#include "../coders/byte_utils.h"
|
||||||
#include "../util/data_io.h"
|
#include "../util/data_io.h"
|
||||||
#include "../coders/json.h"
|
#include "../coders/json.h"
|
||||||
#include "../constants.h"
|
#include "../constants.h"
|
||||||
@ -189,7 +190,7 @@ void WorldFiles::put(Chunk* chunk){
|
|||||||
int localX = chunk->x - (regionX * REGION_SIZE);
|
int localX = chunk->x - (regionX * REGION_SIZE);
|
||||||
int localZ = chunk->z - (regionZ * REGION_SIZE);
|
int localZ = chunk->z - (regionZ * REGION_SIZE);
|
||||||
|
|
||||||
/* Writing Voxels */ {
|
/* Writing voxels */ {
|
||||||
size_t compressedSize;
|
size_t compressedSize;
|
||||||
std::unique_ptr<ubyte[]> chunk_data (chunk->encode());
|
std::unique_ptr<ubyte[]> chunk_data (chunk->encode());
|
||||||
ubyte* data = compress(chunk_data.get(), CHUNK_DATA_LEN, compressedSize);
|
ubyte* data = compress(chunk_data.get(), CHUNK_DATA_LEN, compressedSize);
|
||||||
@ -198,15 +199,39 @@ void WorldFiles::put(Chunk* chunk){
|
|||||||
region->setUnsaved(true);
|
region->setUnsaved(true);
|
||||||
region->put(localX, localZ, data, compressedSize);
|
region->put(localX, localZ, data, compressedSize);
|
||||||
}
|
}
|
||||||
|
/* Writing lights cache */
|
||||||
if (doWriteLights && chunk->isLighted()) {
|
if (doWriteLights && chunk->isLighted()) {
|
||||||
size_t compressedSize;
|
size_t compressedSize;
|
||||||
std::unique_ptr<ubyte[]> light_data (chunk->lightmap->encode());
|
std::unique_ptr<ubyte[]> light_data (chunk->lightmap.encode());
|
||||||
ubyte* data = compress(light_data.get(), LIGHTMAP_DATA_LEN, compressedSize);
|
ubyte* data = compress(light_data.get(), LIGHTMAP_DATA_LEN, compressedSize);
|
||||||
|
|
||||||
WorldRegion* region = getOrCreateRegion(lights, regionX, regionZ);
|
WorldRegion* region = getOrCreateRegion(lights, regionX, regionZ);
|
||||||
region->setUnsaved(true);
|
region->setUnsaved(true);
|
||||||
region->put(localX, localZ, data, compressedSize);
|
region->put(localX, localZ, data, compressedSize);
|
||||||
}
|
}
|
||||||
|
/* Writing block inventories */
|
||||||
|
if (!chunk->inventories.empty()){
|
||||||
|
auto& inventories = chunk->inventories;
|
||||||
|
ByteBuilder builder;
|
||||||
|
builder.putInt32(inventories.size());
|
||||||
|
for (auto& entry : inventories) {
|
||||||
|
builder.putInt32(entry.first);
|
||||||
|
auto map = entry.second->serialize();
|
||||||
|
auto bytes = json::to_binary(map.get(), true);
|
||||||
|
builder.putInt32(bytes.size());
|
||||||
|
builder.put(bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
|
WorldRegion* region = getOrCreateRegion(storages, regionX, regionZ);
|
||||||
|
region->setUnsaved(true);
|
||||||
|
|
||||||
|
auto datavec = builder.data();
|
||||||
|
uint datasize = builder.size();
|
||||||
|
auto data = std::make_unique<ubyte[]>(builder.size());
|
||||||
|
for (uint i = 0; i < builder.size(); i++) {
|
||||||
|
data[i] = datavec[i];
|
||||||
|
}
|
||||||
|
region->put(localX, localZ, data.release(), datasize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getRegionsFolder() const {
|
fs::path WorldFiles::getRegionsFolder() const {
|
||||||
@ -217,6 +242,10 @@ fs::path WorldFiles::getLightsFolder() const {
|
|||||||
return directory/fs::path("lights");
|
return directory/fs::path("lights");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs::path WorldFiles::getInventoriesFolder() const {
|
||||||
|
return directory/fs::path("inventories");
|
||||||
|
}
|
||||||
|
|
||||||
fs::path WorldFiles::getRegionFilename(int x, int z) const {
|
fs::path WorldFiles::getRegionFilename(int x, int z) const {
|
||||||
return fs::path(std::to_string(x) + "_" + std::to_string(z) + ".bin");
|
return fs::path(std::to_string(x) + "_" + std::to_string(z) + ".bin");
|
||||||
}
|
}
|
||||||
@ -436,20 +465,24 @@ void WorldFiles::writeRegions(regionsmap& regions, const fs::path& folder, int l
|
|||||||
void WorldFiles::write(const World* world, const Content* content) {
|
void WorldFiles::write(const World* world, const Content* content) {
|
||||||
fs::path regionsFolder = getRegionsFolder();
|
fs::path regionsFolder = getRegionsFolder();
|
||||||
fs::path lightsFolder = getLightsFolder();
|
fs::path lightsFolder = getLightsFolder();
|
||||||
|
fs::path inventoriesFolder = getInventoriesFolder();
|
||||||
|
|
||||||
fs::create_directories(regionsFolder);
|
fs::create_directories(regionsFolder);
|
||||||
|
fs::create_directories(inventoriesFolder);
|
||||||
fs::create_directories(lightsFolder);
|
fs::create_directories(lightsFolder);
|
||||||
|
|
||||||
if (world) {
|
if (world) {
|
||||||
writeWorldInfo(world);
|
writeWorldInfo(world);
|
||||||
writePacks(world);
|
writePacks(world);
|
||||||
}
|
}
|
||||||
if (generatorTestMode)
|
if (generatorTestMode) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
writeIndices(content->getIndices());
|
writeIndices(content->getIndices());
|
||||||
writeRegions(regions, regionsFolder, REGION_LAYER_VOXELS);
|
writeRegions(regions, regionsFolder, REGION_LAYER_VOXELS);
|
||||||
writeRegions(lights, lightsFolder, REGION_LAYER_LIGHTS);
|
writeRegions(lights, lightsFolder, REGION_LAYER_LIGHTS);
|
||||||
|
writeRegions(storages, inventoriesFolder, REGION_LAYER_STORAGES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::writePacks(const World* world) {
|
void WorldFiles::writePacks(const World* world) {
|
||||||
@ -488,21 +521,7 @@ void WorldFiles::writeIndices(const ContentIndices* indices) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::writeWorldInfo(const World* world) {
|
void WorldFiles::writeWorldInfo(const World* world) {
|
||||||
dynamic::Map root;
|
files::write_json(getWorldFile(), world->serialize().get());
|
||||||
|
|
||||||
auto& versionobj = root.putMap("version");
|
|
||||||
versionobj.put("major", ENGINE_VERSION_MAJOR);
|
|
||||||
versionobj.put("minor", ENGINE_VERSION_MINOR);
|
|
||||||
|
|
||||||
root.put("name", world->getName());
|
|
||||||
root.put("seed", world->getSeed());
|
|
||||||
|
|
||||||
auto& timeobj = root.putMap("time");
|
|
||||||
timeobj.put("day-time", world->daytime);
|
|
||||||
timeobj.put("day-time-speed", world->daytimeSpeed);
|
|
||||||
timeobj.put("total-time", world->totalTime);
|
|
||||||
|
|
||||||
files::write_json(getWorldFile(), &root);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldFiles::readWorldInfo(World* world) {
|
bool WorldFiles::readWorldInfo(World* world) {
|
||||||
@ -513,25 +532,7 @@ bool WorldFiles::readWorldInfo(World* world) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto root = files::read_json(file);
|
auto root = files::read_json(file);
|
||||||
|
world->deserialize(root.get());
|
||||||
world->setName(root->getStr("name", world->getName()));
|
|
||||||
world->setSeed(root->getInt("seed", world->getSeed()));
|
|
||||||
|
|
||||||
auto verobj = root->map("version");
|
|
||||||
if (verobj) {
|
|
||||||
int major=0, minor=-1;
|
|
||||||
verobj->num("major", major);
|
|
||||||
verobj->num("minor", minor);
|
|
||||||
std::cout << "world version: " << major << "." << minor << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto timeobj = root->map("time");
|
|
||||||
if (timeobj) {
|
|
||||||
timeobj->num("day-time", world->daytime);
|
|
||||||
timeobj->num("day-time-speed", world->daytimeSpeed);
|
|
||||||
timeobj->num("total-time", world->totalTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,8 +551,15 @@ bool WorldFiles::readPlayer(Player* player) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::addPack(const std::string& id) {
|
void WorldFiles::addPack(const World* world, const std::string& id) {
|
||||||
auto packs = files::read_list(getPacksFile());
|
fs::path file = getPacksFile();
|
||||||
|
if (!fs::is_regular_file(file)) {
|
||||||
|
if (!fs::is_directory(directory)) {
|
||||||
|
fs::create_directories(directory);
|
||||||
|
}
|
||||||
|
writePacks(world);
|
||||||
|
}
|
||||||
|
auto packs = files::read_list(file);
|
||||||
packs.push_back(id);
|
packs.push_back(id);
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@ -559,5 +567,5 @@ void WorldFiles::addPack(const std::string& id) {
|
|||||||
for (const auto& pack : packs) {
|
for (const auto& pack : packs) {
|
||||||
ss << pack << "\n";
|
ss << pack << "\n";
|
||||||
}
|
}
|
||||||
files::write_string(getPacksFile(), ss.str());
|
files::write_string(file, ss.str());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,8 +16,11 @@
|
|||||||
#include "../settings.h"
|
#include "../settings.h"
|
||||||
|
|
||||||
const uint REGION_HEADER_SIZE = 10;
|
const uint REGION_HEADER_SIZE = 10;
|
||||||
|
|
||||||
const uint REGION_LAYER_VOXELS = 0;
|
const uint REGION_LAYER_VOXELS = 0;
|
||||||
const uint REGION_LAYER_LIGHTS = 1;
|
const uint REGION_LAYER_LIGHTS = 1;
|
||||||
|
const uint REGION_LAYER_STORAGES = 2;
|
||||||
|
|
||||||
const uint REGION_SIZE_BIT = 5;
|
const uint REGION_SIZE_BIT = 5;
|
||||||
const uint REGION_SIZE = (1 << (REGION_SIZE_BIT));
|
const uint REGION_SIZE = (1 << (REGION_SIZE_BIT));
|
||||||
const uint REGION_CHUNKS_COUNT = ((REGION_SIZE) * (REGION_SIZE));
|
const uint REGION_CHUNKS_COUNT = ((REGION_SIZE) * (REGION_SIZE));
|
||||||
@ -74,7 +77,6 @@ class WorldFiles {
|
|||||||
std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;
|
std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;
|
||||||
|
|
||||||
void writeWorldInfo(const World* world);
|
void writeWorldInfo(const World* world);
|
||||||
fs::path getLightsFolder() const;
|
|
||||||
fs::path getRegionFilename(int x, int y) const;
|
fs::path getRegionFilename(int x, int y) const;
|
||||||
fs::path getWorldFile() const;
|
fs::path getWorldFile() const;
|
||||||
fs::path getIndicesFile() const;
|
fs::path getIndicesFile() const;
|
||||||
@ -110,12 +112,16 @@ class WorldFiles {
|
|||||||
int x, int z, int layer);
|
int x, int z, int layer);
|
||||||
|
|
||||||
regfile* getRegFile(glm::ivec3 coord, const fs::path& folder);
|
regfile* getRegFile(glm::ivec3 coord, const fs::path& folder);
|
||||||
|
|
||||||
|
fs::path getLightsFolder() const;
|
||||||
|
fs::path getInventoriesFolder() const;
|
||||||
public:
|
public:
|
||||||
static bool parseRegionFilename(const std::string& name, int& x, int& y);
|
static bool parseRegionFilename(const std::string& name, int& x, int& y);
|
||||||
fs::path getRegionsFolder() const;
|
fs::path getRegionsFolder() const;
|
||||||
fs::path getPlayerFile() const;
|
fs::path getPlayerFile() const;
|
||||||
|
|
||||||
regionsmap regions;
|
regionsmap regions;
|
||||||
|
regionsmap storages;
|
||||||
regionsmap lights;
|
regionsmap lights;
|
||||||
fs::path directory;
|
fs::path directory;
|
||||||
std::unique_ptr<ubyte[]> compressionBuffer;
|
std::unique_ptr<ubyte[]> compressionBuffer;
|
||||||
@ -147,7 +153,7 @@ public:
|
|||||||
void writePacks(const World* world);
|
void writePacks(const World* world);
|
||||||
void writeIndices(const ContentIndices* indices);
|
void writeIndices(const ContentIndices* indices);
|
||||||
/* Append pack to packs.list without duplicate check */
|
/* Append pack to packs.list without duplicate check */
|
||||||
void addPack(const std::string& id);
|
void addPack(const World* world, const std::string& id);
|
||||||
|
|
||||||
static const char* WORLD_FILE;
|
static const char* WORLD_FILE;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -99,10 +99,7 @@ bool files::write_json(fs::path filename, const dynamic::Map* obj, bool nice) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool files::write_binary_json(fs::path filename, const dynamic::Map* obj, bool compression) {
|
bool files::write_binary_json(fs::path filename, const dynamic::Map* obj, bool compression) {
|
||||||
auto bytes = json::to_binary(obj);
|
auto bytes = json::to_binary(obj, compression);
|
||||||
if (compression) {
|
|
||||||
bytes = gzip::compress(bytes.data(), bytes.size());
|
|
||||||
}
|
|
||||||
return files::write_bytes(filename, bytes.data(), bytes.size());
|
return files::write_bytes(filename, bytes.data(), bytes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -172,7 +172,7 @@ std::shared_ptr<InventoryView> HudRenderer::createContentAccess() {
|
|||||||
auto inventory = player->getInventory();
|
auto inventory = player->getInventory();
|
||||||
|
|
||||||
int itemsCount = indices->countItemDefs();
|
int itemsCount = indices->countItemDefs();
|
||||||
auto accessInventory = std::make_shared<Inventory>(itemsCount);
|
auto accessInventory = std::make_shared<Inventory>(0, itemsCount);
|
||||||
for (int id = 1; id < itemsCount; id++) {
|
for (int id = 1; id < itemsCount; id++) {
|
||||||
accessInventory->getSlot(id-1).set(ItemStack(id, 1));
|
accessInventory->getSlot(id-1).set(ItemStack(id, 1));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,7 +252,12 @@ typedef std::function<void(const ContentPack& pack)> packconsumer;
|
|||||||
|
|
||||||
const int PACKS_PANEL_WIDTH = 550;
|
const int PACKS_PANEL_WIDTH = 550;
|
||||||
|
|
||||||
std::shared_ptr<Panel> create_packs_panel(const std::vector<ContentPack>& packs, Engine* engine, bool backbutton, packconsumer callback) {
|
std::shared_ptr<Panel> create_packs_panel(
|
||||||
|
const std::vector<ContentPack>& packs,
|
||||||
|
Engine* engine,
|
||||||
|
bool backbutton,
|
||||||
|
packconsumer callback)
|
||||||
|
{
|
||||||
auto assets = engine->getAssets();
|
auto assets = engine->getAssets();
|
||||||
auto panel = std::make_shared<Panel>(vec2(PACKS_PANEL_WIDTH, 200), vec4(5.0f));
|
auto panel = std::make_shared<Panel>(vec2(PACKS_PANEL_WIDTH, 200), vec4(5.0f));
|
||||||
panel->color(vec4(1.0f, 1.0f, 1.0f, 0.07f));
|
panel->color(vec4(1.0f, 1.0f, 1.0f, 0.07f));
|
||||||
@ -298,8 +303,9 @@ std::shared_ptr<Panel> create_packs_panel(const std::vector<ContentPack>& packs,
|
|||||||
packpanel->color(vec4(0.06f, 0.12f, 0.18f, 0.7f));
|
packpanel->color(vec4(0.06f, 0.12f, 0.18f, 0.7f));
|
||||||
panel->add(packpanel);
|
panel->add(packpanel);
|
||||||
}
|
}
|
||||||
if (backbutton)
|
if (backbutton) {
|
||||||
panel->add(guiutil::backButton(engine->getGUI()->getMenu()));
|
panel->add(guiutil::backButton(engine->getGUI()->getMenu()));
|
||||||
|
}
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,11 +344,11 @@ void create_content_panel(Engine* engine, PagesControl* menu) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!world->hasPack(dependency)) {
|
if (!world->hasPack(dependency)) {
|
||||||
world->wfile->addPack(dependency);
|
world->wfile->addPack(world, dependency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
world->wfile->addPack(pack.id);
|
world->wfile->addPack(world, pack.id);
|
||||||
|
|
||||||
std::string wname = world->getName();
|
std::string wname = world->getName();
|
||||||
engine->setScreen(nullptr);
|
engine->setScreen(nullptr);
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../content/ContentLUT.h"
|
#include "../content/ContentLUT.h"
|
||||||
|
|
||||||
Inventory::Inventory(size_t size) : slots(size) {
|
Inventory::Inventory(uint id, size_t size) : id(id), slots(size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack& Inventory::getSlot(size_t index) {
|
ItemStack& Inventory::getSlot(size_t index) {
|
||||||
@ -45,6 +45,7 @@ void Inventory::move(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Inventory::deserialize(dynamic::Map* src) {
|
void Inventory::deserialize(dynamic::Map* src) {
|
||||||
|
id = src->getNum("id", 1);
|
||||||
auto slotsarr = src->list("slots");
|
auto slotsarr = src->list("slots");
|
||||||
size_t slotscount = std::min(slotsarr->size(), slots.size());
|
size_t slotscount = std::min(slotsarr->size(), slots.size());
|
||||||
for (size_t i = 0; i < slotscount; i++) {
|
for (size_t i = 0; i < slotscount; i++) {
|
||||||
@ -58,6 +59,8 @@ void Inventory::deserialize(dynamic::Map* src) {
|
|||||||
|
|
||||||
std::unique_ptr<dynamic::Map> Inventory::serialize() const {
|
std::unique_ptr<dynamic::Map> Inventory::serialize() const {
|
||||||
auto map = std::make_unique<dynamic::Map>();
|
auto map = std::make_unique<dynamic::Map>();
|
||||||
|
map->put("id", id);
|
||||||
|
|
||||||
auto& slotsarr = map->putList("slots");
|
auto& slotsarr = map->putList("slots");
|
||||||
for (size_t i = 0; i < slots.size(); i++) {
|
for (size_t i = 0; i < slots.size(); i++) {
|
||||||
auto& item = slots[i];
|
auto& item = slots[i];
|
||||||
|
|||||||
@ -13,11 +13,11 @@
|
|||||||
class ContentLUT;
|
class ContentLUT;
|
||||||
class ContentIndices;
|
class ContentIndices;
|
||||||
|
|
||||||
// TODO: items indices fix
|
|
||||||
class Inventory : Serializable {
|
class Inventory : Serializable {
|
||||||
|
uint id;
|
||||||
std::vector<ItemStack> slots;
|
std::vector<ItemStack> slots;
|
||||||
public:
|
public:
|
||||||
Inventory(size_t size);
|
Inventory(uint id, size_t size);
|
||||||
|
|
||||||
ItemStack& getSlot(size_t index);
|
ItemStack& getSlot(size_t index);
|
||||||
size_t findEmptySlot(size_t begin=0, size_t end=-1) const;
|
size_t findEmptySlot(size_t begin=0, size_t end=-1) const;
|
||||||
@ -40,6 +40,10 @@ public:
|
|||||||
|
|
||||||
static void convert(dynamic::Map* data, const ContentLUT* lut);
|
static void convert(dynamic::Map* data, const ContentLUT* lut);
|
||||||
|
|
||||||
|
inline uint getId() const {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
static const size_t npos;
|
static const size_t npos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ void LightSolver::add(int x, int y, int z, int emission) {
|
|||||||
|
|
||||||
Chunk* chunk = chunks->getChunkByVoxel(x, y, z);
|
Chunk* chunk = chunks->getChunkByVoxel(x, y, z);
|
||||||
chunk->setModified(true);
|
chunk->setModified(true);
|
||||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, emission);
|
chunk->lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, emission);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightSolver::add(int x, int y, int z) {
|
void LightSolver::add(int x, int y, int z) {
|
||||||
@ -35,12 +35,12 @@ void LightSolver::remove(int x, int y, int z) {
|
|||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ubyte light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel);
|
ubyte light = chunk->lightmap.get(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel);
|
||||||
if (light == 0){
|
if (light == 0){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
remqueue.push(lightentry {x, y, z, light});
|
remqueue.push(lightentry {x, y, z, light});
|
||||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0);
|
chunk->lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightSolver::solve(){
|
void LightSolver::solve(){
|
||||||
@ -67,10 +67,10 @@ void LightSolver::solve(){
|
|||||||
int lz = z - chunk->z * CHUNK_D;
|
int lz = z - chunk->z * CHUNK_D;
|
||||||
chunk->setModified(true);
|
chunk->setModified(true);
|
||||||
|
|
||||||
ubyte light = chunk->lightmap->get(lx,y,lz, channel);
|
ubyte light = chunk->lightmap.get(lx,y,lz, channel);
|
||||||
if (light != 0 && light == entry.light-1){
|
if (light != 0 && light == entry.light-1){
|
||||||
remqueue.push(lightentry {x, y, z, light});
|
remqueue.push(lightentry {x, y, z, light});
|
||||||
chunk->lightmap->set(lx, y, lz, channel, 0);
|
chunk->lightmap.set(lx, y, lz, channel, 0);
|
||||||
}
|
}
|
||||||
else if (light >= entry.light){
|
else if (light >= entry.light){
|
||||||
addqueue.push(lightentry {x, y, z, light});
|
addqueue.push(lightentry {x, y, z, light});
|
||||||
@ -94,11 +94,11 @@ void LightSolver::solve(){
|
|||||||
int lz = z - chunk->z * CHUNK_D;
|
int lz = z - chunk->z * CHUNK_D;
|
||||||
chunk->setModified(true);
|
chunk->setModified(true);
|
||||||
|
|
||||||
ubyte light = chunk->lightmap->get(lx, y, lz, channel);
|
ubyte light = chunk->lightmap.get(lx, y, lz, channel);
|
||||||
voxel& v = chunk->voxels[vox_index(lx, y, lz)];
|
voxel& v = chunk->voxels[vox_index(lx, y, lz)];
|
||||||
const Block* block = blockDefs[v.id];
|
const Block* block = blockDefs[v.id];
|
||||||
if (block->lightPassing && light+2 <= entry.light){
|
if (block->lightPassing && light+2 <= entry.light){
|
||||||
chunk->lightmap->set(
|
chunk->lightmap.set(
|
||||||
x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D,
|
x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D,
|
||||||
channel,
|
channel,
|
||||||
entry.light-1);
|
entry.light-1);
|
||||||
|
|||||||
@ -29,9 +29,9 @@ void Lighting::clear(){
|
|||||||
auto chunk = chunks->chunks[index];
|
auto chunk = chunks->chunks[index];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
continue;
|
continue;
|
||||||
Lightmap* lightmap = chunk->lightmap;
|
Lightmap& lightmap = chunk->lightmap;
|
||||||
for (int i = 0; i < CHUNK_VOL; i++){
|
for (int i = 0; i < CHUNK_VOL; i++){
|
||||||
lightmap->map[i] = 0;
|
lightmap.map[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,13 +51,13 @@ void Lighting::prebuildSkyLight(Chunk* chunk, const ContentIndices* indices){
|
|||||||
highestPoint = y;
|
highestPoint = y;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
chunk->lightmap->setS(x,y,z, 15);
|
chunk->lightmap.setS(x,y,z, 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (highestPoint < CHUNK_H-1)
|
if (highestPoint < CHUNK_H-1)
|
||||||
highestPoint++;
|
highestPoint++;
|
||||||
chunk->lightmap->highestPoint = highestPoint;
|
chunk->lightmap.highestPoint = highestPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lighting::buildSkyLight(int cx, int cz){
|
void Lighting::buildSkyLight(int cx, int cz){
|
||||||
@ -66,13 +66,13 @@ void Lighting::buildSkyLight(int cx, int cz){
|
|||||||
Chunk* chunk = chunks->getChunk(cx, cz);
|
Chunk* chunk = chunks->getChunk(cx, cz);
|
||||||
for (int z = 0; z < CHUNK_D; z++){
|
for (int z = 0; z < CHUNK_D; z++){
|
||||||
for (int x = 0; x < CHUNK_W; x++){
|
for (int x = 0; x < CHUNK_W; x++){
|
||||||
for (int y = chunk->lightmap->highestPoint; y >= 0; y--){
|
for (int y = chunk->lightmap.highestPoint; y >= 0; y--){
|
||||||
int gx = x + cx * CHUNK_W;
|
int gx = x + cx * CHUNK_W;
|
||||||
int gz = z + cz * CHUNK_D;
|
int gz = z + cz * CHUNK_D;
|
||||||
while (y > 0 && !blockDefs[chunk->voxels[vox_index(x, y, z)].id]->lightPassing) {
|
while (y > 0 && !blockDefs[chunk->voxels[vox_index(x, y, z)].id]->lightPassing) {
|
||||||
y--;
|
y--;
|
||||||
}
|
}
|
||||||
if (chunk->lightmap->getS(x, y, z) != 15) {
|
if (chunk->lightmap.getS(x, y, z) != 15) {
|
||||||
solverS->add(gx,y+1,gz);
|
solverS->add(gx,y+1,gz);
|
||||||
for (; y >= 0; y--){
|
for (; y >= 0; y--){
|
||||||
solverS->add(gx+1,y,gz);
|
solverS->add(gx+1,y,gz);
|
||||||
@ -99,7 +99,7 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand){
|
|||||||
for (uint y = 0; y < CHUNK_H; y++){
|
for (uint y = 0; y < CHUNK_H; y++){
|
||||||
for (uint z = 0; z < CHUNK_D; z++){
|
for (uint z = 0; z < CHUNK_D; z++){
|
||||||
for (uint x = 0; x < CHUNK_W; x++){
|
for (uint x = 0; x < CHUNK_W; x++){
|
||||||
voxel& vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
const voxel& vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||||
const Block* block = blockDefs[vox.id];
|
const Block* block = blockDefs[vox.id];
|
||||||
int gx = x + cx * CHUNK_W;
|
int gx = x + cx * CHUNK_W;
|
||||||
int gz = z + cz * CHUNK_D;
|
int gz = z + cz * CHUNK_D;
|
||||||
@ -118,7 +118,7 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand){
|
|||||||
for (int z = 0; z < CHUNK_D; z++) {
|
for (int z = 0; z < CHUNK_D; z++) {
|
||||||
int gx = x + cx * CHUNK_W;
|
int gx = x + cx * CHUNK_W;
|
||||||
int gz = z + cz * CHUNK_D;
|
int gz = z + cz * CHUNK_D;
|
||||||
int rgbs = chunk->lightmap->get(x, y, z);
|
int rgbs = chunk->lightmap.get(x, y, z);
|
||||||
if (rgbs){
|
if (rgbs){
|
||||||
solverR->add(gx,y,gz, Lightmap::extract(rgbs, 0));
|
solverR->add(gx,y,gz, Lightmap::extract(rgbs, 0));
|
||||||
solverG->add(gx,y,gz, Lightmap::extract(rgbs, 1));
|
solverG->add(gx,y,gz, Lightmap::extract(rgbs, 1));
|
||||||
@ -133,7 +133,7 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand){
|
|||||||
for (int x = 0; x < CHUNK_W; x++) {
|
for (int x = 0; x < CHUNK_W; x++) {
|
||||||
int gx = x + cx * CHUNK_W;
|
int gx = x + cx * CHUNK_W;
|
||||||
int gz = z + cz * CHUNK_D;
|
int gz = z + cz * CHUNK_D;
|
||||||
int rgbs = chunk->lightmap->get(x, y, z);
|
int rgbs = chunk->lightmap.get(x, y, z);
|
||||||
if (rgbs){
|
if (rgbs){
|
||||||
solverR->add(gx,y,gz, Lightmap::extract(rgbs, 0));
|
solverR->add(gx,y,gz, Lightmap::extract(rgbs, 0));
|
||||||
solverG->add(gx,y,gz, Lightmap::extract(rgbs, 1));
|
solverG->add(gx,y,gz, Lightmap::extract(rgbs, 1));
|
||||||
|
|||||||
@ -3,26 +3,14 @@
|
|||||||
|
|
||||||
#include "../util/data_io.h"
|
#include "../util/data_io.h"
|
||||||
|
|
||||||
Lightmap::Lightmap(){
|
|
||||||
map = new light_t[CHUNK_VOL];
|
|
||||||
for (uint i = 0; i < CHUNK_VOL; i++){
|
|
||||||
map[i] = 0x0000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Lightmap::~Lightmap(){
|
|
||||||
delete[] map;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lightmap::set(const Lightmap* lightmap) {
|
void Lightmap::set(const Lightmap* lightmap) {
|
||||||
for (unsigned int i = 0; i < CHUNK_VOL; i++){
|
set(lightmap->map);
|
||||||
map[i] = lightmap->map[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lightmap::set(light_t* map) {
|
void Lightmap::set(const light_t* map) {
|
||||||
delete[] this->map;
|
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||||
this->map = map;
|
this->map[i] = map[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(sizeof(light_t) == 2, "replace dataio calls to new light_t");
|
static_assert(sizeof(light_t) == 2, "replace dataio calls to new light_t");
|
||||||
|
|||||||
@ -3,43 +3,40 @@
|
|||||||
|
|
||||||
#include "../constants.h"
|
#include "../constants.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../voxels/Chunk.h"
|
|
||||||
|
|
||||||
const int LIGHTMAP_DATA_LEN = CHUNK_VOL/2;
|
const int LIGHTMAP_DATA_LEN = CHUNK_VOL/2;
|
||||||
|
|
||||||
// Lichtkarte
|
// Lichtkarte
|
||||||
class Lightmap {
|
class Lightmap {
|
||||||
public:
|
public:
|
||||||
light_t* map;
|
light_t map[CHUNK_VOL] {};
|
||||||
int highestPoint = 0;
|
int highestPoint = 0;
|
||||||
Lightmap();
|
|
||||||
~Lightmap();
|
|
||||||
|
|
||||||
void set(const Lightmap* lightmap);
|
void set(const Lightmap* lightmap);
|
||||||
|
|
||||||
void set(light_t* map);
|
void set(const light_t* map);
|
||||||
|
|
||||||
inline unsigned short get(int x, int y, int z){
|
inline unsigned short get(int x, int y, int z) const {
|
||||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x]);
|
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned char get(int x, int y, int z, int channel){
|
inline unsigned char get(int x, int y, int z, int channel) const {
|
||||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> (channel << 2)) & 0xF;
|
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> (channel << 2)) & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned char getR(int x, int y, int z){
|
inline unsigned char getR(int x, int y, int z) const {
|
||||||
return map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] & 0xF;
|
return map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned char getG(int x, int y, int z){
|
inline unsigned char getG(int x, int y, int z) const {
|
||||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 4) & 0xF;
|
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 4) & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned char getB(int x, int y, int z){
|
inline unsigned char getB(int x, int y, int z) const {
|
||||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 8) & 0xF;
|
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 8) & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned char getS(int x, int y, int z){
|
inline unsigned char getS(int x, int y, int z) const {
|
||||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 12) & 0xF;
|
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 12) & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,10 +5,12 @@
|
|||||||
#include "../voxels/Chunk.h"
|
#include "../voxels/Chunk.h"
|
||||||
#include "../voxels/Chunks.h"
|
#include "../voxels/Chunks.h"
|
||||||
#include "../world/Level.h"
|
#include "../world/Level.h"
|
||||||
|
#include "../world/World.h"
|
||||||
#include "../content/Content.h"
|
#include "../content/Content.h"
|
||||||
#include "../lighting/Lighting.h"
|
#include "../lighting/Lighting.h"
|
||||||
#include "../util/timeutil.h"
|
#include "../util/timeutil.h"
|
||||||
#include "../maths/fastmaths.h"
|
#include "../maths/fastmaths.h"
|
||||||
|
#include "../items/Inventory.h"
|
||||||
|
|
||||||
#include "scripting/scripting.h"
|
#include "scripting/scripting.h"
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,7 @@ public:
|
|||||||
void update(float delta);
|
void update(float delta);
|
||||||
void randomTick(int tickid, int parts);
|
void randomTick(int tickid, int parts);
|
||||||
void onBlocksTick(int tickid, int parts);
|
void onBlocksTick(int tickid, int parts);
|
||||||
|
uint createBlockInventory(int x, int y, int z);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LOGIC_BLOCKS_CONTROLLER_H_
|
#endif // LOGIC_BLOCKS_CONTROLLER_H_
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const float JUMP_FORCE = 8.0f;
|
|||||||
Player::Player(glm::vec3 position, float speed) :
|
Player::Player(glm::vec3 position, float speed) :
|
||||||
speed(speed),
|
speed(speed),
|
||||||
chosenSlot(0),
|
chosenSlot(0),
|
||||||
inventory(new Inventory(40)),
|
inventory(new Inventory(0, 40)),
|
||||||
camera(new Camera(position, glm::radians(90.0f))),
|
camera(new Camera(position, glm::radians(90.0f))),
|
||||||
spCamera(new Camera(position, glm::radians(90.0f))),
|
spCamera(new Camera(position, glm::radians(90.0f))),
|
||||||
tpCamera(new Camera(position, glm::radians(90.0f))),
|
tpCamera(new Camera(position, glm::radians(90.0f))),
|
||||||
|
|||||||
@ -97,6 +97,7 @@ public:
|
|||||||
BlockRotProfile rotations;
|
BlockRotProfile rotations;
|
||||||
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
||||||
std::string scriptName = name.substr(name.find(':')+1);
|
std::string scriptName = name.substr(name.find(':')+1);
|
||||||
|
uint inventorySize = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
blockid_t id;
|
blockid_t id;
|
||||||
|
|||||||
@ -1,30 +1,23 @@
|
|||||||
#include "Chunk.h"
|
#include "Chunk.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
|
|
||||||
|
#include "../items/Inventory.h"
|
||||||
#include "../content/ContentLUT.h"
|
#include "../content/ContentLUT.h"
|
||||||
#include "../lighting/Lightmap.h"
|
#include "../lighting/Lightmap.h"
|
||||||
|
|
||||||
Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){
|
Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){
|
||||||
bottom = 0;
|
bottom = 0;
|
||||||
top = CHUNK_H;
|
top = CHUNK_H;
|
||||||
voxels = new voxel[CHUNK_VOL];
|
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
|
||||||
voxels[i].id = 2;
|
voxels[i].id = 2;
|
||||||
voxels[i].states = 0;
|
voxels[i].states = 0;
|
||||||
}
|
}
|
||||||
lightmap = new Lightmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk::~Chunk(){
|
|
||||||
delete lightmap;
|
|
||||||
delete[] voxels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chunk::isEmpty(){
|
bool Chunk::isEmpty(){
|
||||||
int id = -1;
|
int id = -1;
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++){
|
for (uint i = 0; i < CHUNK_VOL; i++){
|
||||||
if (voxels[i].id != id){
|
if (voxels[i].id != id){
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
return false;
|
return false;
|
||||||
@ -36,13 +29,12 @@ bool Chunk::isEmpty(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::updateHeights() {
|
void Chunk::updateHeights() {
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||||
if (voxels[i].id != 0) {
|
if (voxels[i].id != 0) {
|
||||||
bottom = i / (CHUNK_D * CHUNK_W);
|
bottom = i / (CHUNK_D * CHUNK_W);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = CHUNK_VOL - 1; i >= 0; i--) {
|
for (int i = CHUNK_VOL - 1; i >= 0; i--) {
|
||||||
if (voxels[i].id != 0) {
|
if (voxels[i].id != 0) {
|
||||||
top = i / (CHUNK_D * CHUNK_W) + 1;
|
top = i / (CHUNK_D * CHUNK_W) + 1;
|
||||||
@ -51,11 +43,28 @@ void Chunk::updateHeights() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunk::clone() const {
|
void Chunk::addBlockInventory(std::shared_ptr<Inventory> inventory,
|
||||||
Chunk* other = new Chunk(x,z);
|
uint x, uint y, uint z) {
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++)
|
inventories[vox_index(x, y, z)] = inventory;
|
||||||
|
setUnsaved(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Inventory> Chunk::getBlockInventory(uint x, uint y, uint z) const {
|
||||||
|
if (x >= CHUNK_W || y >= CHUNK_H || z >= CHUNK_D)
|
||||||
|
return nullptr;
|
||||||
|
const auto& found = inventories.find(vox_index(x, y, z));
|
||||||
|
if (found == inventories.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Chunk> Chunk::clone() const {
|
||||||
|
auto other = std::make_unique<Chunk>(x,z);
|
||||||
|
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||||
other->voxels[i] = voxels[i];
|
other->voxels[i] = voxels[i];
|
||||||
other->lightmap->set(lightmap);
|
}
|
||||||
|
other->lightmap.set(&lightmap);
|
||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +84,7 @@ Chunk* Chunk::clone() const {
|
|||||||
*/
|
*/
|
||||||
ubyte* Chunk::encode() const {
|
ubyte* Chunk::encode() const {
|
||||||
ubyte* buffer = new ubyte[CHUNK_DATA_LEN];
|
ubyte* buffer = new ubyte[CHUNK_DATA_LEN];
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||||
buffer[i] = voxels[i].id >> 8;
|
buffer[i] = voxels[i].id >> 8;
|
||||||
buffer[CHUNK_VOL+i] = voxels[i].id & 0xFF;
|
buffer[CHUNK_VOL+i] = voxels[i].id & 0xFF;
|
||||||
buffer[CHUNK_VOL*2 + i] = voxels[i].states >> 8;
|
buffer[CHUNK_VOL*2 + i] = voxels[i].states >> 8;
|
||||||
@ -84,11 +93,8 @@ ubyte* Chunk::encode() const {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if all is fine
|
|
||||||
**/
|
|
||||||
bool Chunk::decode(ubyte* data) {
|
bool Chunk::decode(ubyte* data) {
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||||
voxel& vox = voxels[i];
|
voxel& vox = voxels[i];
|
||||||
|
|
||||||
ubyte bid1 = data[i];
|
ubyte bid1 = data[i];
|
||||||
@ -104,7 +110,7 @@ bool Chunk::decode(ubyte* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::convert(ubyte* data, const ContentLUT* lut) {
|
void Chunk::convert(ubyte* data, const ContentLUT* lut) {
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||||
// see encode method to understand what the hell is going on here
|
// see encode method to understand what the hell is going on here
|
||||||
blockid_t id = ((blockid_t(data[i]) << 8) |
|
blockid_t id = ((blockid_t(data[i]) << 8) |
|
||||||
blockid_t(data[CHUNK_VOL+i]));
|
blockid_t(data[CHUNK_VOL+i]));
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
#ifndef VOXELS_CHUNK_H_
|
#ifndef VOXELS_CHUNK_H_
|
||||||
#define VOXELS_CHUNK_H_
|
#define VOXELS_CHUNK_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "../constants.h"
|
#include "../constants.h"
|
||||||
|
#include "voxel.h"
|
||||||
|
#include "../lighting/Lightmap.h"
|
||||||
|
|
||||||
struct ChunkFlag {
|
struct ChunkFlag {
|
||||||
static const int MODIFIED = 0x1;
|
static const int MODIFIED = 0x1;
|
||||||
@ -14,26 +19,29 @@ struct ChunkFlag {
|
|||||||
};
|
};
|
||||||
#define CHUNK_DATA_LEN (CHUNK_VOL*4)
|
#define CHUNK_DATA_LEN (CHUNK_VOL*4)
|
||||||
|
|
||||||
struct voxel;
|
|
||||||
class Lightmap;
|
class Lightmap;
|
||||||
class ContentLUT;
|
class ContentLUT;
|
||||||
|
class Inventory;
|
||||||
|
|
||||||
class Chunk {
|
class Chunk {
|
||||||
public:
|
public:
|
||||||
int x, z;
|
int x, z;
|
||||||
int bottom, top;
|
int bottom, top;
|
||||||
voxel* voxels;
|
voxel voxels[CHUNK_VOL];
|
||||||
Lightmap* lightmap;
|
Lightmap lightmap;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
|
/* Block inventories map where key is index of block in voxels array */
|
||||||
|
std::unordered_map<uint, std::shared_ptr<Inventory>> inventories;
|
||||||
|
|
||||||
Chunk(int x, int z);
|
Chunk(int x, int z);
|
||||||
~Chunk();
|
|
||||||
|
|
||||||
bool isEmpty();
|
bool isEmpty();
|
||||||
|
|
||||||
void updateHeights();
|
void updateHeights();
|
||||||
|
|
||||||
Chunk* clone() const;
|
// unused
|
||||||
|
std::unique_ptr<Chunk> clone() const;
|
||||||
|
|
||||||
// flags getters/setters below
|
// flags getters/setters below
|
||||||
inline void setFlags(int mask, bool value){
|
inline void setFlags(int mask, bool value){
|
||||||
@ -43,6 +51,14 @@ public:
|
|||||||
flags &= ~(mask);
|
flags &= ~(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Creates new block inventory given size
|
||||||
|
@return inventory id or 0 if block does not exists */
|
||||||
|
void addBlockInventory(std::shared_ptr<Inventory> inventory,
|
||||||
|
uint x, uint y, uint z);
|
||||||
|
|
||||||
|
/* @return inventory bound to the given block or nullptr */
|
||||||
|
std::shared_ptr<Inventory> getBlockInventory(uint x, uint y, uint z) const;
|
||||||
|
|
||||||
inline bool isUnsaved() const {return flags & ChunkFlag::UNSAVED;}
|
inline bool isUnsaved() const {return flags & ChunkFlag::UNSAVED;}
|
||||||
|
|
||||||
inline bool isModified() const {return flags & ChunkFlag::MODIFIED;}
|
inline bool isModified() const {return flags & ChunkFlag::MODIFIED;}
|
||||||
@ -68,6 +84,10 @@ public:
|
|||||||
inline void setReady(bool newState) {setFlags(ChunkFlag::READY, newState);}
|
inline void setReady(bool newState) {setFlags(ChunkFlag::READY, newState);}
|
||||||
|
|
||||||
ubyte* encode() const;
|
ubyte* encode() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if all is fine
|
||||||
|
**/
|
||||||
bool decode(ubyte* data);
|
bool decode(ubyte* data);
|
||||||
|
|
||||||
static void convert(ubyte* data, const ContentLUT* lut);
|
static void convert(ubyte* data, const ContentLUT* lut);
|
||||||
|
|||||||
@ -107,7 +107,7 @@ ubyte Chunks::getLight(int x, int y, int z, int channel){
|
|||||||
int lx = x - cx * CHUNK_W;
|
int lx = x - cx * CHUNK_W;
|
||||||
int ly = y - cy * CHUNK_H;
|
int ly = y - cy * CHUNK_H;
|
||||||
int lz = z - cz * CHUNK_D;
|
int lz = z - cz * CHUNK_D;
|
||||||
return chunk->lightmap->get(lx,ly,lz, channel);
|
return chunk->lightmap.get(lx,ly,lz, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
light_t Chunks::getLight(int x, int y, int z){
|
light_t Chunks::getLight(int x, int y, int z){
|
||||||
@ -124,7 +124,7 @@ light_t Chunks::getLight(int x, int y, int z){
|
|||||||
int lx = x - cx * CHUNK_W;
|
int lx = x - cx * CHUNK_W;
|
||||||
int ly = y - cy * CHUNK_H;
|
int ly = y - cy * CHUNK_H;
|
||||||
int lz = z - cz * CHUNK_D;
|
int lz = z - cz * CHUNK_D;
|
||||||
return chunk->lightmap->get(lx,ly,lz);
|
return chunk->lightmap.get(lx,ly,lz);
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
|
Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
|
||||||
|
|||||||
@ -61,9 +61,9 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
|||||||
verifyLoadedChunk(level->content->getIndices(), chunk.get());
|
verifyLoadedChunk(level->content->getIndices(), chunk.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
light_t* lights = wfile->getLights(chunk->x, chunk->z);
|
std::unique_ptr<light_t[]> lights (wfile->getLights(chunk->x, chunk->z));
|
||||||
if (lights) {
|
if (lights) {
|
||||||
chunk->lightmap->set(lights);
|
chunk->lightmap.set(lights.get());
|
||||||
chunk->setLoadedLights(true);
|
chunk->setLoadedLights(true);
|
||||||
}
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
@ -114,7 +114,7 @@ void ChunksStorage::getVoxels(VoxelsVolume* volume, bool backlight) const {
|
|||||||
} else {
|
} else {
|
||||||
auto& chunk = found->second;
|
auto& chunk = found->second;
|
||||||
const voxel* cvoxels = chunk->voxels;
|
const voxel* cvoxels = chunk->voxels;
|
||||||
const light_t* clights = chunk->lightmap->getLights();
|
const light_t* clights = chunk->lightmap.getLights();
|
||||||
for (int ly = y; ly < y + h; ly++) {
|
for (int ly = y; ly < y + h; ly++) {
|
||||||
for (int lz = max(z, cz * CHUNK_D);
|
for (int lz = max(z, cz * CHUNK_D);
|
||||||
lz < min(z + d, (cz + 1) * CHUNK_D);
|
lz < min(z + d, (cz + 1) * CHUNK_D);
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "../physics/Hitbox.h"
|
#include "../physics/Hitbox.h"
|
||||||
#include "../physics/PhysicsSolver.h"
|
#include "../physics/PhysicsSolver.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
|
#include "../items/Inventory.h"
|
||||||
|
|
||||||
Level::Level(World* world, const Content* content, Player* player, EngineSettings& settings)
|
Level::Level(World* world, const Content* content, Player* player, EngineSettings& settings)
|
||||||
: world(world),
|
: world(world),
|
||||||
@ -16,7 +17,8 @@ Level::Level(World* world, const Content* content, Player* player, EngineSetting
|
|||||||
player(player),
|
player(player),
|
||||||
chunksStorage(new ChunksStorage(this)),
|
chunksStorage(new ChunksStorage(this)),
|
||||||
events(new LevelEvents()) ,
|
events(new LevelEvents()) ,
|
||||||
settings(settings) {
|
settings(settings)
|
||||||
|
{
|
||||||
physics = new PhysicsSolver(glm::vec3(0, -22.6f, 0));
|
physics = new PhysicsSolver(glm::vec3(0, -22.6f, 0));
|
||||||
|
|
||||||
uint matrixSize = (settings.chunks.loadDistance+
|
uint matrixSize = (settings.chunks.loadDistance+
|
||||||
|
|||||||
@ -10,6 +10,7 @@ class Content;
|
|||||||
class World;
|
class World;
|
||||||
class Player;
|
class Player;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
|
class Inventory;
|
||||||
class LevelEvents;
|
class LevelEvents;
|
||||||
class Lighting;
|
class Lighting;
|
||||||
class PhysicsSolver;
|
class PhysicsSolver;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "Level.h"
|
#include "Level.h"
|
||||||
@ -71,20 +72,11 @@ Level* World::create(std::string name,
|
|||||||
EngineSettings& settings,
|
EngineSettings& settings,
|
||||||
const Content* content,
|
const Content* content,
|
||||||
const std::vector<ContentPack>& packs) {
|
const std::vector<ContentPack>& packs) {
|
||||||
World* world = new World(name, directory, seed, settings, content, packs);
|
auto world = new World(name, directory, seed, settings, content, packs);
|
||||||
Player* player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
|
auto player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
|
||||||
return new Level(world, content, player, settings);
|
return new Level(world, content, player, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentLUT* World::checkIndices(const fs::path& directory,
|
|
||||||
const Content* content) {
|
|
||||||
fs::path indicesFile = directory/fs::path("indices.json");
|
|
||||||
if (fs::is_regular_file(indicesFile)) {
|
|
||||||
return ContentLUT::create(indicesFile, content);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Level* World::load(fs::path directory,
|
Level* World::load(fs::path directory,
|
||||||
EngineSettings& settings,
|
EngineSettings& settings,
|
||||||
const Content* content,
|
const Content* content,
|
||||||
@ -98,14 +90,23 @@ Level* World::load(fs::path directory,
|
|||||||
throw world_load_error("could not to find world.json");
|
throw world_load_error("could not to find world.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
Player* player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
|
auto player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
|
||||||
Level* level = new Level(world.get(), content, player, settings);
|
auto level = new Level(world.get(), content, player, settings);
|
||||||
wfile->readPlayer(player);
|
wfile->readPlayer(player);
|
||||||
|
|
||||||
world.release();
|
world.release();
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContentLUT* World::checkIndices(const fs::path& directory,
|
||||||
|
const Content* content) {
|
||||||
|
fs::path indicesFile = directory/fs::path("indices.json");
|
||||||
|
if (fs::is_regular_file(indicesFile)) {
|
||||||
|
return ContentLUT::create(indicesFile, content);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void World::setName(const std::string& name) {
|
void World::setName(const std::string& name) {
|
||||||
this->name = name;
|
this->name = name;
|
||||||
}
|
}
|
||||||
@ -133,3 +134,44 @@ uint64_t World::getSeed() const {
|
|||||||
const std::vector<ContentPack>& World::getPacks() const {
|
const std::vector<ContentPack>& World::getPacks() const {
|
||||||
return packs;
|
return packs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::deserialize(dynamic::Map* root) {
|
||||||
|
name = root->getStr("name", name);
|
||||||
|
seed = root->getInt("seed", seed);
|
||||||
|
|
||||||
|
auto verobj = root->map("version");
|
||||||
|
if (verobj) {
|
||||||
|
int major=0, minor=-1;
|
||||||
|
verobj->num("major", major);
|
||||||
|
verobj->num("minor", minor);
|
||||||
|
std::cout << "world version: " << major << "." << minor << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto timeobj = root->map("time");
|
||||||
|
if (timeobj) {
|
||||||
|
timeobj->num("day-time", daytime);
|
||||||
|
timeobj->num("day-time-speed", daytimeSpeed);
|
||||||
|
timeobj->num("total-time", totalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
nextInventoryId = root->getNum("next-inventory-id", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<dynamic::Map> World::serialize() const {
|
||||||
|
auto root = std::make_unique<dynamic::Map>();
|
||||||
|
|
||||||
|
auto& versionobj = root->putMap("version");
|
||||||
|
versionobj.put("major", ENGINE_VERSION_MAJOR);
|
||||||
|
versionobj.put("minor", ENGINE_VERSION_MINOR);
|
||||||
|
|
||||||
|
root->put("name", name);
|
||||||
|
root->put("seed", seed);
|
||||||
|
|
||||||
|
auto& timeobj = root->putMap("time");
|
||||||
|
timeobj.put("day-time", daytime);
|
||||||
|
timeobj.put("day-time-speed", daytimeSpeed);
|
||||||
|
timeobj.put("total-time", totalTime);
|
||||||
|
|
||||||
|
root->put("next-inventory-id", nextInventoryId);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,8 @@
|
|||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../settings.h"
|
#include "../settings.h"
|
||||||
#include "../util/timeutil.h"
|
#include "../util/timeutil.h"
|
||||||
|
#include "../data/dynamic.h"
|
||||||
|
#include "../interfaces/Serializable.h"
|
||||||
#include "../content/ContentPack.h"
|
#include "../content/ContentPack.h"
|
||||||
|
|
||||||
class Content;
|
class Content;
|
||||||
@ -25,12 +26,14 @@ public:
|
|||||||
world_load_error(std::string message);
|
world_load_error(std::string message);
|
||||||
};
|
};
|
||||||
|
|
||||||
class World {
|
class World : Serializable {
|
||||||
std::string name;
|
std::string name;
|
||||||
uint64_t seed;
|
uint64_t seed;
|
||||||
EngineSettings& settings;
|
EngineSettings& settings;
|
||||||
const Content* const content;
|
const Content* const content;
|
||||||
std::vector<ContentPack> packs;
|
std::vector<ContentPack> packs;
|
||||||
|
|
||||||
|
uint nextInventoryId = 1;
|
||||||
public:
|
public:
|
||||||
WorldFiles* wfile;
|
WorldFiles* wfile;
|
||||||
|
|
||||||
@ -74,6 +77,13 @@ public:
|
|||||||
std::string getName() const;
|
std::string getName() const;
|
||||||
uint64_t getSeed() const;
|
uint64_t getSeed() const;
|
||||||
const std::vector<ContentPack>& getPacks() const;
|
const std::vector<ContentPack>& getPacks() const;
|
||||||
|
|
||||||
|
std::unique_ptr<dynamic::Map> serialize() const override;
|
||||||
|
void deserialize(dynamic::Map *src) override;
|
||||||
|
|
||||||
|
uint getNextInventoryId() {
|
||||||
|
return nextInventoryId++;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* WORLD_WORLD_H_ */
|
#endif /* WORLD_WORLD_H_ */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user