Refactor, world.bin file, BinaryWriter, BinaryReader
This commit is contained in:
+71
-38
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "rle.h"
|
#include "rle.h"
|
||||||
|
#include "binary_io.h"
|
||||||
#include "../window/Camera.h"
|
#include "../window/Camera.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../physics/Hitbox.h"
|
#include "../physics/Hitbox.h"
|
||||||
@@ -23,6 +24,8 @@
|
|||||||
#define PLAYER_FLAG_FLIGHT 0x1
|
#define PLAYER_FLAG_FLIGHT 0x1
|
||||||
#define PLAYER_FLAG_NOCLIP 0x2
|
#define PLAYER_FLAG_NOCLIP 0x2
|
||||||
|
|
||||||
|
#define WORLD_SECTION_MAIN 1
|
||||||
|
|
||||||
using glm::ivec2;
|
using glm::ivec2;
|
||||||
using glm::vec3;
|
using glm::vec3;
|
||||||
using std::ios;
|
using std::ios;
|
||||||
@@ -40,14 +43,6 @@ void int2Bytes(int value, ubyte* dest, size_t offset){
|
|||||||
dest[offset+3] = (char) (value >> 0 & 255);
|
dest[offset+3] = (char) (value >> 0 & 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void floatToBytes(float fvalue, ubyte* dest, size_t offset){
|
|
||||||
uint32_t value = *((uint32_t*)&fvalue);
|
|
||||||
dest[offset] = (char) (value >> 24 & 255);
|
|
||||||
dest[offset+1] = (char) (value >> 16 & 255);
|
|
||||||
dest[offset+2] = (char) (value >> 8 & 255);
|
|
||||||
dest[offset+3] = (char) (value >> 0 & 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
float bytes2Float(ubyte* src, uint offset){
|
float bytes2Float(ubyte* src, uint offset){
|
||||||
uint32_t value = ((src[offset] << 24) |
|
uint32_t value = ((src[offset] << 24) |
|
||||||
(src[offset+1] << 16) |
|
(src[offset+1] << 16) |
|
||||||
@@ -56,7 +51,7 @@ float bytes2Float(ubyte* src, uint offset){
|
|||||||
return *(float*)(&value);
|
return *(float*)(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldFiles::WorldFiles(path directory, size_t mainBufferCapacity, bool generatorTestMode)
|
WorldFiles::WorldFiles(path directory, bool generatorTestMode)
|
||||||
: directory(directory), generatorTestMode(generatorTestMode) {
|
: directory(directory), generatorTestMode(generatorTestMode) {
|
||||||
compressionBuffer = new ubyte[CHUNK_DATA_LEN * 2];
|
compressionBuffer = new ubyte[CHUNK_DATA_LEN * 2];
|
||||||
}
|
}
|
||||||
@@ -115,14 +110,18 @@ void WorldFiles::put(Chunk* chunk){
|
|||||||
region.compressedSizes[chunk_index] = compressedSize;
|
region.compressedSizes[chunk_index] = compressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
path WorldFiles::getRegionFile(int x, int y) {
|
path WorldFiles::getRegionFile(int x, int y) const {
|
||||||
return directory/path(std::to_string(x) + "_" + std::to_string(y) + ".bin");
|
return directory/path(std::to_string(x) + "_" + std::to_string(y) + ".bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
path WorldFiles::getPlayerFile() {
|
path WorldFiles::getPlayerFile() const {
|
||||||
return directory/path("player.bin");
|
return directory/path("player.bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path WorldFiles::getWorldFile() const {
|
||||||
|
return directory/path("world.bin");
|
||||||
|
}
|
||||||
|
|
||||||
ubyte* WorldFiles::getChunk(int x, int y){
|
ubyte* WorldFiles::getChunk(int x, int y){
|
||||||
int regionX = floordiv(x, REGION_SIZE);
|
int regionX = floordiv(x, REGION_SIZE);
|
||||||
int regionY = floordiv(y, REGION_SIZE);
|
int regionY = floordiv(y, REGION_SIZE);
|
||||||
@@ -199,10 +198,11 @@ ubyte* WorldFiles::readChunkData(int x, int y, uint32_t& length){
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::write(){
|
void WorldFiles::write(const WorldInfo info){
|
||||||
if (!std::filesystem::is_directory(directory)) {
|
if (!std::filesystem::is_directory(directory)) {
|
||||||
std::filesystem::create_directories(directory);
|
std::filesystem::create_directories(directory);
|
||||||
}
|
}
|
||||||
|
writeWorldInfo(info);
|
||||||
if (generatorTestMode)
|
if (generatorTestMode)
|
||||||
return;
|
return;
|
||||||
for (auto it = regions.begin(); it != regions.end(); it++){
|
for (auto it = regions.begin(); it != regions.end(); it++){
|
||||||
@@ -213,26 +213,58 @@ void WorldFiles::write(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::writePlayer(Player* player){
|
void WorldFiles::writeWorldInfo(const WorldInfo& info) {
|
||||||
ubyte dst[1+3*4 + 1+2*4 + 1+1];
|
BinaryWriter out;
|
||||||
|
out.putCStr(WORLD_FORMAT_MAGIC);
|
||||||
|
out.put(WORLD_FORMAT_VERSION);
|
||||||
|
out.put(WORLD_SECTION_MAIN);
|
||||||
|
|
||||||
|
out.putInt64(info.seed);
|
||||||
|
out.put(info.name);
|
||||||
|
|
||||||
|
files::write_bytes(getWorldFile(), (const char*)out.data(), out.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WorldFiles::readWorldInfo(WorldInfo& info) {
|
||||||
|
size_t length = 0;
|
||||||
|
ubyte* data = (ubyte*)files::read_bytes(getPlayerFile(), length);
|
||||||
|
if (data == nullptr){
|
||||||
|
std::cerr << "could not to read world.bin (ignored)" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BinaryReader inp(data, length);
|
||||||
|
inp.checkMagic(WORLD_FORMAT_MAGIC, length);
|
||||||
|
/*ubyte version = */inp.get();
|
||||||
|
while (inp.hasNext()) {
|
||||||
|
ubyte section = inp.get();
|
||||||
|
switch (section) {
|
||||||
|
case WORLD_SECTION_MAIN:
|
||||||
|
info.seed = inp.getInt64();
|
||||||
|
info.name = inp.getString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldFiles::writePlayer(Player* player){
|
||||||
vec3 position = player->hitbox->position;
|
vec3 position = player->hitbox->position;
|
||||||
|
|
||||||
size_t offset = 0;
|
BinaryWriter out;
|
||||||
dst[offset++] = SECTION_POSITION;
|
out.put(SECTION_POSITION);
|
||||||
floatToBytes(position.x, dst, offset); offset += 4;
|
out.putFloat32(position.x);
|
||||||
floatToBytes(position.y, dst, offset); offset += 4;
|
out.putFloat32(position.y);
|
||||||
floatToBytes(position.z, dst, offset); offset += 4;
|
out.putFloat32(position.z);
|
||||||
|
|
||||||
dst[offset++] = SECTION_ROTATION;
|
out.put(SECTION_ROTATION);
|
||||||
floatToBytes(player->camX, dst, offset); offset += 4;
|
out.putFloat32(player->camX);
|
||||||
floatToBytes(player->camY, dst, offset); offset += 4;
|
out.putFloat32(player->camY);
|
||||||
|
|
||||||
dst[offset++] = SECTION_FLAGS;
|
out.put(SECTION_FLAGS);
|
||||||
dst[offset++] = player->flight * PLAYER_FLAG_FLIGHT |
|
out.put(player->flight * PLAYER_FLAG_FLIGHT |
|
||||||
player->noclip * PLAYER_FLAG_NOCLIP;
|
player->noclip * PLAYER_FLAG_NOCLIP);
|
||||||
|
|
||||||
files::write_bytes(getPlayerFile(), (const char*)dst, sizeof(dst));
|
files::write_bytes(getPlayerFile(), (const char*)out.data(), out.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldFiles::readPlayer(Player* player) {
|
bool WorldFiles::readPlayer(Player* player) {
|
||||||
@@ -243,28 +275,29 @@ bool WorldFiles::readPlayer(Player* player) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
vec3 position = player->hitbox->position;
|
vec3 position = player->hitbox->position;
|
||||||
size_t offset = 0;
|
BinaryReader inp(data, length);
|
||||||
while (offset < length){
|
while (inp.hasNext()) {
|
||||||
char section = data[offset++];
|
ubyte section = inp.get();
|
||||||
switch (section){
|
switch (section) {
|
||||||
case SECTION_POSITION:
|
case SECTION_POSITION:
|
||||||
position.x = bytes2Float(data, offset); offset += 4;
|
position.x = inp.getFloat32();
|
||||||
position.y = bytes2Float(data, offset); offset += 4;
|
position.y = inp.getFloat32();
|
||||||
position.z = bytes2Float(data, offset); offset += 4;
|
position.z = inp.getFloat32();
|
||||||
break;
|
break;
|
||||||
case SECTION_ROTATION:
|
case SECTION_ROTATION:
|
||||||
player->camX = bytes2Float(data, offset); offset += 4;
|
player->camX = inp.getFloat32();
|
||||||
player->camY = bytes2Float(data, offset); offset += 4;
|
player->camY = inp.getFloat32();
|
||||||
break;
|
break;
|
||||||
case SECTION_FLAGS:
|
case SECTION_FLAGS:
|
||||||
{
|
{
|
||||||
ubyte flags = data[offset++];
|
ubyte flags = inp.get();
|
||||||
player->flight = flags & PLAYER_FLAG_FLIGHT;
|
player->flight = flags & PLAYER_FLAG_FLIGHT;
|
||||||
player->noclip = flags & PLAYER_FLAG_NOCLIP;
|
player->noclip = flags & PLAYER_FLAG_NOCLIP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player->hitbox->position = position;
|
player->hitbox->position = position;
|
||||||
player->camera->position = position + vec3(0, 1, 0);
|
player->camera->position = position + vec3(0, 1, 0);
|
||||||
return true;
|
return true;
|
||||||
@@ -281,7 +314,7 @@ void WorldFiles::writeRegion(int x, int y, WorldRegion& entry){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char header[10] = ".VOXREG";
|
char header[10] = REGION_FORMAT_MAGIC;
|
||||||
header[8] = REGION_FORMAT_VERSION;
|
header[8] = REGION_FORMAT_VERSION;
|
||||||
header[9] = 0; // flags
|
header[9] = 0; // flags
|
||||||
std::ofstream file(getRegionFile(x, y), ios::out | ios::binary);
|
std::ofstream file(getRegionFile(x, y), ios::out | ios::binary);
|
||||||
|
|||||||
+16
-5
@@ -17,6 +17,9 @@
|
|||||||
#define REGION_SIZE (1 << (REGION_SIZE_BIT))
|
#define REGION_SIZE (1 << (REGION_SIZE_BIT))
|
||||||
#define REGION_VOL ((REGION_SIZE) * (REGION_SIZE))
|
#define REGION_VOL ((REGION_SIZE) * (REGION_SIZE))
|
||||||
#define REGION_FORMAT_VERSION 1
|
#define REGION_FORMAT_VERSION 1
|
||||||
|
#define REGION_FORMAT_MAGIC ".VOXREG"
|
||||||
|
#define WORLD_FORMAT_MAGIC ".VOXWLD"
|
||||||
|
#define WORLD_FORMAT_VERSION 1
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
class Chunk;
|
class Chunk;
|
||||||
@@ -27,27 +30,35 @@ struct WorldRegion {
|
|||||||
bool unsaved;
|
bool unsaved;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WorldInfo {
|
||||||
|
std::string name;
|
||||||
|
std::filesystem::path directory;
|
||||||
|
uint64_t seed;
|
||||||
|
};
|
||||||
|
|
||||||
class WorldFiles {
|
class WorldFiles {
|
||||||
|
void writeWorldInfo(const WorldInfo& info);
|
||||||
|
std::filesystem::path getRegionFile(int x, int y) const;
|
||||||
|
std::filesystem::path getPlayerFile() const;
|
||||||
|
std::filesystem::path getWorldFile() const;
|
||||||
public:
|
public:
|
||||||
std::unordered_map<glm::ivec2, WorldRegion> regions;
|
std::unordered_map<glm::ivec2, WorldRegion> regions;
|
||||||
std::filesystem::path directory;
|
std::filesystem::path directory;
|
||||||
ubyte* compressionBuffer;
|
ubyte* compressionBuffer;
|
||||||
bool generatorTestMode;
|
bool generatorTestMode;
|
||||||
|
|
||||||
WorldFiles(std::filesystem::path directory, size_t mainBufferCapacity, bool generatorTestMode);
|
WorldFiles(std::filesystem::path directory, bool generatorTestMode);
|
||||||
~WorldFiles();
|
~WorldFiles();
|
||||||
|
|
||||||
void put(Chunk* chunk);
|
void put(Chunk* chunk);
|
||||||
|
|
||||||
|
bool readWorldInfo(WorldInfo& info);
|
||||||
bool readPlayer(Player* player);
|
bool readPlayer(Player* player);
|
||||||
ubyte* readChunkData(int x, int y, uint32_t& length);
|
ubyte* readChunkData(int x, int y, uint32_t& length);
|
||||||
ubyte* getChunk(int x, int y);
|
ubyte* getChunk(int x, int y);
|
||||||
void writeRegion(int x, int y, WorldRegion& entry);
|
void writeRegion(int x, int y, WorldRegion& entry);
|
||||||
void writePlayer(Player* player);
|
void writePlayer(Player* player);
|
||||||
void write();
|
void write(const WorldInfo info);
|
||||||
|
|
||||||
std::filesystem::path getRegionFile(int x, int y);
|
|
||||||
std::filesystem::path getPlayerFile();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FILES_WORLDFILES_H_ */
|
#endif /* FILES_WORLDFILES_H_ */
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#include "binary_io.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
void BinaryWriter::put(ubyte b) {
|
||||||
|
buffer.push_back(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::putCStr(const char* str) {
|
||||||
|
size_t size = strlen(str)+1;
|
||||||
|
buffer.reserve(buffer.size() + size);
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
buffer.push_back(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::put(const string& s) {
|
||||||
|
size_t len = s.length();
|
||||||
|
if (len > INT16_MAX) {
|
||||||
|
throw std::domain_error("length > INT16_MAX");
|
||||||
|
}
|
||||||
|
putInt16(len);
|
||||||
|
put((const ubyte*)s.data(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::put(const ubyte* arr, size_t size) {
|
||||||
|
buffer.reserve(buffer.size() + size);
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
buffer.push_back(arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::putInt16(int16_t val) {
|
||||||
|
buffer.push_back((char) (val >> 8 & 255));
|
||||||
|
buffer.push_back((char) (val >> 0 & 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::putInt32(int32_t val) {
|
||||||
|
buffer.reserve(buffer.size() + 4);
|
||||||
|
buffer.push_back((char) (val >> 24 & 255));
|
||||||
|
buffer.push_back((char) (val >> 16 & 255));
|
||||||
|
buffer.push_back((char) (val >> 8 & 255));
|
||||||
|
buffer.push_back((char) (val >> 0 & 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::putInt64(int64_t val) {
|
||||||
|
buffer.reserve(buffer.size() + 8);
|
||||||
|
buffer.push_back((char) (val >> 56 & 255));
|
||||||
|
buffer.push_back((char) (val >> 48 & 255));
|
||||||
|
buffer.push_back((char) (val >> 40 & 255));
|
||||||
|
buffer.push_back((char) (val >> 32 & 255));
|
||||||
|
buffer.push_back((char) (val >> 24 & 255));
|
||||||
|
buffer.push_back((char) (val >> 16 & 255));
|
||||||
|
buffer.push_back((char) (val >> 8 & 255));
|
||||||
|
buffer.push_back((char) (val >> 0 & 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::putFloat32(float val) {
|
||||||
|
putInt32(*((uint32_t*)&val));
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryReader::BinaryReader(const ubyte* data, size_t size)
|
||||||
|
: data(data), size(size), pos(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryReader::checkMagic(const char* data, size_t size) {
|
||||||
|
if (pos + size >= this->size) {
|
||||||
|
throw std::runtime_error("invalid magic number");
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
if (this->data[pos + i] != (ubyte)data[i]){
|
||||||
|
throw std::runtime_error("invalid magic number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubyte BinaryReader::get() {
|
||||||
|
if (pos == size) {
|
||||||
|
throw std::underflow_error("buffer underflow");
|
||||||
|
}
|
||||||
|
return data[pos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t BinaryReader::getInt16() {
|
||||||
|
if (pos+2 >= size) {
|
||||||
|
throw std::underflow_error("unexpected end");
|
||||||
|
}
|
||||||
|
pos += 2;
|
||||||
|
return (data[pos - 2] << 8) |
|
||||||
|
(data[pos - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t BinaryReader::getInt32() {
|
||||||
|
if (pos+4 >= size) {
|
||||||
|
throw std::underflow_error("unexpected end");
|
||||||
|
}
|
||||||
|
pos += 4;
|
||||||
|
return (data[pos - 4] << 24) |
|
||||||
|
(data[pos - 3] << 16) |
|
||||||
|
(data[pos - 2] << 8) |
|
||||||
|
(data[pos - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t BinaryReader::getInt64() {
|
||||||
|
if (pos+8 >= size) {
|
||||||
|
throw std::underflow_error("unexpected end");
|
||||||
|
}
|
||||||
|
pos += 8;
|
||||||
|
return ((int64_t)data[pos - 8] << 56) |
|
||||||
|
((int64_t)data[pos - 7] << 48) |
|
||||||
|
((int64_t)data[pos - 6] << 40) |
|
||||||
|
((int64_t)data[pos - 5] << 32) |
|
||||||
|
((int64_t)data[pos - 4] << 24) |
|
||||||
|
((int64_t)data[pos - 3] << 16) |
|
||||||
|
((int64_t)data[pos - 2] << 8) |
|
||||||
|
((int64_t)data[pos - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float BinaryReader::getFloat32() {
|
||||||
|
int32_t value = getInt32();
|
||||||
|
return *(float*)(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
string BinaryReader::getString() {
|
||||||
|
uint16_t length = (uint16_t)getInt16();
|
||||||
|
if (pos+length >= size) {
|
||||||
|
throw std::underflow_error("unexpected end");
|
||||||
|
}
|
||||||
|
pos += length;
|
||||||
|
return string((const char*)(data+pos-length), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryReader::hasNext() const {
|
||||||
|
return pos < size;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef FILES_BINARY_WRITER_H_
|
||||||
|
#define FILES_BINARY_WRITER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
class BinaryWriter {
|
||||||
|
std::vector<ubyte> buffer;
|
||||||
|
public:
|
||||||
|
void put(ubyte b);
|
||||||
|
void putCStr(const char* str);
|
||||||
|
void putInt16(int16_t val);
|
||||||
|
void putInt32(int32_t val);
|
||||||
|
void putInt64(int64_t val);
|
||||||
|
void putFloat32(float val);
|
||||||
|
void put(const std::string& s);
|
||||||
|
void put(const ubyte* arr, size_t size);
|
||||||
|
|
||||||
|
inline size_t size() const {
|
||||||
|
return buffer.size();
|
||||||
|
}
|
||||||
|
inline const ubyte* data() const {
|
||||||
|
return buffer.data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BinaryReader {
|
||||||
|
const ubyte* data;
|
||||||
|
size_t size;
|
||||||
|
size_t pos;
|
||||||
|
public:
|
||||||
|
BinaryReader(const ubyte* data, size_t size);
|
||||||
|
|
||||||
|
void checkMagic(const char* data, size_t size);
|
||||||
|
ubyte get();
|
||||||
|
int16_t getInt16();
|
||||||
|
int32_t getInt32();
|
||||||
|
int64_t getInt64();
|
||||||
|
float getFloat32();
|
||||||
|
std::string getString();
|
||||||
|
bool hasNext() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILES_BINARY_WRITER_H_
|
||||||
@@ -46,7 +46,7 @@ MenuScreen::MenuScreen(Engine* engine_) : Screen(engine_) {
|
|||||||
path folder = enginefs::get_worlds_folder()/path("world");
|
path folder = enginefs::get_worlds_folder()/path("world");
|
||||||
World* world = new World("world", folder, 42, settings);
|
World* world = new World("world", folder, 42, settings);
|
||||||
|
|
||||||
auto screen = new LevelScreen(engine, world->loadLevel(settings));
|
auto screen = new LevelScreen(engine, world->load(settings));
|
||||||
engine->setScreen(shared_ptr<Screen>(screen));
|
engine->setScreen(shared_ptr<Screen>(screen));
|
||||||
});
|
});
|
||||||
panel->add(shared_ptr<UINode>(button));
|
panel->add(shared_ptr<UINode>(button));
|
||||||
|
|||||||
+33
-32
@@ -97,17 +97,15 @@ light_t Chunks::getLight(int x, int y, int z){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
|
Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
|
||||||
|
if (y < 0 || y >= CHUNK_H)
|
||||||
|
return nullptr;
|
||||||
x -= ox * CHUNK_W;
|
x -= ox * CHUNK_W;
|
||||||
z -= oz * CHUNK_D;
|
z -= oz * CHUNK_D;
|
||||||
int cx = x / CHUNK_W;
|
int cx = floordiv(x, CHUNK_W);
|
||||||
int cy = y / CHUNK_H;
|
int cz = floordiv(z, CHUNK_D);
|
||||||
int cz = z / CHUNK_D;
|
if (cx < 0 || cz < 0 || cx >= w || cz >= d)
|
||||||
if (x < 0) cx--;
|
|
||||||
if (y < 0) cy--;
|
|
||||||
if (z < 0) cz--;
|
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return chunks[(cy * d + cz) * w + cx].get();
|
return chunks[cz * w + cx].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunks::getChunk(int x, int z){
|
Chunk* Chunks::getChunk(int x, int z){
|
||||||
@@ -119,14 +117,12 @@ Chunk* Chunks::getChunk(int x, int z){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::set(int x, int y, int z, int id, uint8_t states){
|
void Chunks::set(int x, int y, int z, int id, uint8_t states){
|
||||||
x -= ox * CHUNK_W;
|
|
||||||
z -= oz * CHUNK_D;
|
|
||||||
int cx = x / CHUNK_W;
|
|
||||||
if (y < 0 || y >= CHUNK_H)
|
if (y < 0 || y >= CHUNK_H)
|
||||||
return;
|
return;
|
||||||
int cz = z / CHUNK_D;
|
x -= ox * CHUNK_W;
|
||||||
if (x < 0) cx--;
|
z -= oz * CHUNK_D;
|
||||||
if (z < 0) cz--;
|
int cx = floordiv(x, CHUNK_W);
|
||||||
|
int cz = floordiv(z, CHUNK_D);
|
||||||
if (cx < 0 || cz < 0 || cx >= w || cz >= d)
|
if (cx < 0 || cz < 0 || cx >= w || cz >= d)
|
||||||
return;
|
return;
|
||||||
Chunk* chunk = chunks[cz * w + cx].get();
|
Chunk* chunk = chunks[cz * w + cx].get();
|
||||||
@@ -143,17 +139,26 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){
|
|||||||
else if (y + 1 > chunk->top) chunk->top = y + 1;
|
else if (y + 1 > chunk->top) chunk->top = y + 1;
|
||||||
else if (id == 0) chunk->updateHeights();
|
else if (id == 0) chunk->updateHeights();
|
||||||
|
|
||||||
if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz))) chunk->setModified(true);
|
if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz)))
|
||||||
if (lz == 0 && (chunk = getChunk(cx+ox, cz+oz-1))) chunk->setModified(true);
|
chunk->setModified(true);
|
||||||
|
if (lz == 0 && (chunk = getChunk(cx+ox, cz+oz-1)))
|
||||||
|
chunk->setModified(true);
|
||||||
|
|
||||||
if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cz+oz))) chunk->setModified(true);
|
if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cz+oz)))
|
||||||
if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cz+oz+1))) chunk->setModified(true);
|
chunk->setModified(true);
|
||||||
|
if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cz+oz+1)))
|
||||||
|
chunk->setModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, vec3& iend) {
|
voxel* Chunks::rayCast(vec3 start,
|
||||||
float px = a.x;
|
vec3 dir,
|
||||||
float py = a.y;
|
float maxDist,
|
||||||
float pz = a.z;
|
vec3& end,
|
||||||
|
vec3& norm,
|
||||||
|
vec3& iend) {
|
||||||
|
float px = start.x;
|
||||||
|
float py = start.y;
|
||||||
|
float pz = start.z;
|
||||||
|
|
||||||
float dx = dir.x;
|
float dx = dir.x;
|
||||||
float dy = dir.y;
|
float dy = dir.y;
|
||||||
@@ -239,14 +244,10 @@ voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::setCenter(int x, int z) {
|
void Chunks::setCenter(int x, int z) {
|
||||||
int cx = x / CHUNK_W;
|
int cx = floordiv(x, CHUNK_W);
|
||||||
int cz = z / CHUNK_D;
|
int cz = floordiv(z, CHUNK_D);
|
||||||
cx -= ox;
|
cx -= ox + w / 2;
|
||||||
cz -= oz;
|
cz -= oz + d / 2;
|
||||||
if (x < 0) cx--;
|
|
||||||
if (z < 0) cz--;
|
|
||||||
cx -= w/2;
|
|
||||||
cz -= d/2;
|
|
||||||
if (cx | cz) {
|
if (cx | cz) {
|
||||||
translate(cx,cz);
|
translate(cx,cz);
|
||||||
}
|
}
|
||||||
@@ -295,8 +296,8 @@ void Chunks::resize(int newW, int newD) {
|
|||||||
translate(0, delta);
|
translate(0, delta);
|
||||||
}
|
}
|
||||||
const int newVolume = newW * newD;
|
const int newVolume = newW * newD;
|
||||||
shared_ptr<Chunk>* newChunks = new shared_ptr<Chunk>[newVolume] {};
|
auto newChunks = new shared_ptr<Chunk>[newVolume] {};
|
||||||
shared_ptr<Chunk>* newChunksSecond = new shared_ptr<Chunk>[newVolume] {};
|
auto newChunksSecond = new shared_ptr<Chunk>[newVolume] {};
|
||||||
for (int z = 0; z < d && z < newD; z++) {
|
for (int z = 0; z < d && z < newD; z++) {
|
||||||
for (int x = 0; x < w && x < newW; x++) {
|
for (int x = 0; x < w && x < newW; x++) {
|
||||||
newChunks[z * newW + x] = chunks[z * w + x];
|
newChunks[z * newW + x] = chunks[z * w + x];
|
||||||
|
|||||||
+10
-2
@@ -13,6 +13,7 @@ class voxel;
|
|||||||
class WorldFiles;
|
class WorldFiles;
|
||||||
class LevelEvents;
|
class LevelEvents;
|
||||||
|
|
||||||
|
/* Player-centred chunks matrix */
|
||||||
class Chunks {
|
class Chunks {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<Chunk>* chunks;
|
std::shared_ptr<Chunk>* chunks;
|
||||||
@@ -25,7 +26,8 @@ public:
|
|||||||
WorldFiles* worldFiles;
|
WorldFiles* worldFiles;
|
||||||
LevelEvents* events;
|
LevelEvents* events;
|
||||||
|
|
||||||
Chunks(int w, int d, int ox, int oz, WorldFiles* worldFiles, LevelEvents* events);
|
Chunks(int w, int d, int ox, int oz,
|
||||||
|
WorldFiles* worldFiles, LevelEvents* events);
|
||||||
~Chunks();
|
~Chunks();
|
||||||
|
|
||||||
bool putChunk(std::shared_ptr<Chunk> chunk);
|
bool putChunk(std::shared_ptr<Chunk> chunk);
|
||||||
@@ -36,7 +38,13 @@ public:
|
|||||||
light_t getLight(int x, int y, int z);
|
light_t getLight(int x, int y, int z);
|
||||||
ubyte getLight(int x, int y, int z, int channel);
|
ubyte getLight(int x, int y, int z, int channel);
|
||||||
void set(int x, int y, int z, int id, uint8_t states);
|
void set(int x, int y, int z, int id, uint8_t states);
|
||||||
voxel* rayCast(glm::vec3 start, glm::vec3 dir, float maxLength, glm::vec3& end, glm::vec3& norm, glm::vec3& iend);
|
|
||||||
|
voxel* rayCast(glm::vec3 start,
|
||||||
|
glm::vec3 dir,
|
||||||
|
float maxLength,
|
||||||
|
glm::vec3& end,
|
||||||
|
glm::vec3& norm,
|
||||||
|
glm::vec3& iend);
|
||||||
|
|
||||||
bool isObstacle(int x, int y, int z);
|
bool isObstacle(int x, int y, int z);
|
||||||
|
|
||||||
|
|||||||
@@ -15,16 +15,10 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(__MINGW32__)
|
|
||||||
#define _WIN32_WINNT 0x0501
|
|
||||||
#include <mingw.thread.h>
|
|
||||||
#else
|
|
||||||
#include <thread>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_WORK_PER_FRAME 16
|
#define MAX_WORK_PER_FRAME 16
|
||||||
#define MIN_SURROUNDING 9
|
#define MIN_SURROUNDING 9
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
using std::chrono::high_resolution_clock;
|
using std::chrono::high_resolution_clock;
|
||||||
using std::chrono::duration_cast;
|
using std::chrono::duration_cast;
|
||||||
@@ -63,8 +57,8 @@ bool ChunksController::loadVisible(){
|
|||||||
int nearX = 0;
|
int nearX = 0;
|
||||||
int nearZ = 0;
|
int nearZ = 0;
|
||||||
int minDistance = ((w-padding*2)/2)*((w-padding*2)/2);
|
int minDistance = ((w-padding*2)/2)*((w-padding*2)/2);
|
||||||
for (int z = padding; z < d-padding; z++){
|
for (uint z = padding; z < d-padding; z++){
|
||||||
for (int x = padding; x < w-padding; x++){
|
for (uint x = padding; x < w-padding; x++){
|
||||||
int index = z * w + x;
|
int index = z * w + x;
|
||||||
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||||
if (chunk != nullptr){
|
if (chunk != nullptr){
|
||||||
@@ -101,14 +95,7 @@ bool ChunksController::loadVisible(){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = shared_ptr<Chunk>(new Chunk(nearX+ox, nearZ+oz));
|
chunk = level->chunksStorage->create(nearX+ox, nearZ+oz);
|
||||||
level->chunksStorage->store(chunk);
|
|
||||||
ubyte* data = level->world->wfile->getChunk(chunk->x, chunk->z);
|
|
||||||
if (data) {
|
|
||||||
chunk->decode(data);
|
|
||||||
chunk->setLoaded(true);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
chunks->putChunk(chunk);
|
chunks->putChunk(chunk);
|
||||||
|
|
||||||
if (!chunk->isLoaded()) {
|
if (!chunk->isLoaded()) {
|
||||||
|
|||||||
@@ -4,14 +4,18 @@
|
|||||||
|
|
||||||
#include "VoxelsVolume.h"
|
#include "VoxelsVolume.h"
|
||||||
#include "Chunk.h"
|
#include "Chunk.h"
|
||||||
|
#include "../files/WorldFiles.h"
|
||||||
|
#include "../world/Level.h"
|
||||||
|
#include "../world/World.h"
|
||||||
#include "../maths/voxmaths.h"
|
#include "../maths/voxmaths.h"
|
||||||
#include "../lighting/Lightmap.h"
|
#include "../lighting/Lightmap.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
using glm::ivec2;
|
using glm::ivec2;
|
||||||
|
using std::unique_ptr;
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
|
|
||||||
ChunksStorage::ChunksStorage() {
|
ChunksStorage::ChunksStorage(Level* level) : level(level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunksStorage::~ChunksStorage() {
|
ChunksStorage::~ChunksStorage() {
|
||||||
@@ -36,6 +40,17 @@ void ChunksStorage::remove(int x, int z) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||||
|
auto chunk = shared_ptr<Chunk>(new Chunk(x, z));
|
||||||
|
store(chunk);
|
||||||
|
unique_ptr<ubyte> data(level->world->wfile->getChunk(chunk->x, chunk->z));
|
||||||
|
if (data) {
|
||||||
|
chunk->decode(data.get());
|
||||||
|
chunk->setLoaded(true);
|
||||||
|
}
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
// some magic code
|
// some magic code
|
||||||
void ChunksStorage::getVoxels(VoxelsVolume* volume) const {
|
void ChunksStorage::getVoxels(VoxelsVolume* volume) const {
|
||||||
voxel* voxels = volume->getVoxels();
|
voxel* voxels = volume->getVoxels();
|
||||||
@@ -70,13 +85,13 @@ void ChunksStorage::getVoxels(VoxelsVolume* volume) const {
|
|||||||
for (int lx = max(x, cx * CHUNK_W);
|
for (int lx = max(x, cx * CHUNK_W);
|
||||||
lx < min(x + w, (cx + 1) * CHUNK_W);
|
lx < min(x + w, (cx + 1) * CHUNK_W);
|
||||||
lx++) {
|
lx++) {
|
||||||
voxels[vox_index(lx - x, ly - y, lz - z, w, d)].id = BLOCK_VOID;
|
uint idx = vox_index(lx - x, ly - y, lz - z, w, d);
|
||||||
lights[vox_index(lx - x, ly - y, lz - z, w, d)] = 0;
|
voxels[idx].id = BLOCK_VOID;
|
||||||
|
lights[idx] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
const std::shared_ptr<Chunk>& chunk = found->second;
|
const std::shared_ptr<Chunk>& 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();
|
||||||
@@ -87,10 +102,11 @@ void ChunksStorage::getVoxels(VoxelsVolume* volume) const {
|
|||||||
for (int lx = max(x, cx * CHUNK_W);
|
for (int lx = max(x, cx * CHUNK_W);
|
||||||
lx < min(x + w, (cx + 1) * CHUNK_W);
|
lx < min(x + w, (cx + 1) * CHUNK_W);
|
||||||
lx++) {
|
lx++) {
|
||||||
voxels[vox_index(lx - x, ly - y, lz - z, w, d)] =
|
uint vidx = vox_index(lx - x, ly - y, lz - z, w, d);
|
||||||
cvoxels[vox_index(lx - cx * CHUNK_W, ly, lz - cz * CHUNK_D, CHUNK_W, CHUNK_D)];
|
uint cidx = vox_index(lx - cx * CHUNK_W, ly,
|
||||||
lights[vox_index(lx - x, ly - y, lz - z, w, d)] =
|
lz - cz * CHUNK_D, CHUNK_W, CHUNK_D);
|
||||||
clights[vox_index(lx - cx * CHUNK_W, ly, lz - cz * CHUNK_D, CHUNK_W, CHUNK_D)];
|
voxels[vidx] = cvoxels[cidx];
|
||||||
|
lights[vidx] = clights[cidx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,18 +10,21 @@
|
|||||||
#include "glm/gtx/hash.hpp"
|
#include "glm/gtx/hash.hpp"
|
||||||
|
|
||||||
class Chunk;
|
class Chunk;
|
||||||
|
class Level;
|
||||||
class VoxelsVolume;
|
class VoxelsVolume;
|
||||||
|
|
||||||
class ChunksStorage {
|
class ChunksStorage {
|
||||||
|
Level* level;
|
||||||
std::unordered_map<glm::ivec2, std::shared_ptr<Chunk>> chunksMap;
|
std::unordered_map<glm::ivec2, std::shared_ptr<Chunk>> chunksMap;
|
||||||
public:
|
public:
|
||||||
ChunksStorage();
|
ChunksStorage(Level* level);
|
||||||
virtual ~ChunksStorage();
|
virtual ~ChunksStorage();
|
||||||
|
|
||||||
std::shared_ptr<Chunk> get(int x, int y) const;
|
std::shared_ptr<Chunk> get(int x, int z) const;
|
||||||
void store(std::shared_ptr<Chunk> chunk);
|
void store(std::shared_ptr<Chunk> chunk);
|
||||||
void remove(int x, int y);
|
void remove(int x, int y);
|
||||||
void getVoxels(VoxelsVolume* volume) const;
|
void getVoxels(VoxelsVolume* volume) const;
|
||||||
|
std::shared_ptr<Chunk> create(int x, int z);
|
||||||
|
|
||||||
light_t getLight(int x, int y, int z, ubyte channel) const;
|
light_t getLight(int x, int y, int z, ubyte channel) const;
|
||||||
};
|
};
|
||||||
|
|||||||
+6
-5
@@ -11,11 +11,11 @@
|
|||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../objects/player_control.h"
|
#include "../objects/player_control.h"
|
||||||
|
|
||||||
Level::Level(World* world, Player* player, ChunksStorage* chunksStorage, LevelEvents* events, EngineSettings& settings) :
|
Level::Level(World* world, Player* player, EngineSettings& settings)
|
||||||
world(world),
|
: world(world),
|
||||||
player(player),
|
player(player),
|
||||||
chunksStorage(chunksStorage),
|
chunksStorage(new ChunksStorage(this)),
|
||||||
events(events) {
|
events(new LevelEvents()) {
|
||||||
physics = new PhysicsSolver(vec3(0, -19.6f, 0));
|
physics = new PhysicsSolver(vec3(0, -19.6f, 0));
|
||||||
|
|
||||||
uint matrixSize = (settings.chunks.loadDistance+
|
uint matrixSize = (settings.chunks.loadDistance+
|
||||||
@@ -25,7 +25,8 @@ Level::Level(World* world, Player* player, ChunksStorage* chunksStorage, LevelEv
|
|||||||
world->wfile,
|
world->wfile,
|
||||||
events);
|
events);
|
||||||
lighting = new Lighting(chunks);
|
lighting = new Lighting(chunks);
|
||||||
chunksController = new ChunksController(this, chunks, lighting, settings.chunks.padding);
|
chunksController = new ChunksController(this, chunks, lighting,
|
||||||
|
settings.chunks.padding);
|
||||||
playerController = new PlayerController(this, settings);
|
playerController = new PlayerController(this, settings);
|
||||||
|
|
||||||
events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) {
|
events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) {
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ public:
|
|||||||
|
|
||||||
Level(World* world,
|
Level(World* world,
|
||||||
Player* player,
|
Player* player,
|
||||||
ChunksStorage* chunksStorage,
|
|
||||||
LevelEvents* events,
|
|
||||||
EngineSettings& settings);
|
EngineSettings& settings);
|
||||||
~Level();
|
~Level();
|
||||||
|
|
||||||
|
|||||||
+15
-9
@@ -9,15 +9,19 @@
|
|||||||
#include "../voxels/Chunks.h"
|
#include "../voxels/Chunks.h"
|
||||||
#include "../voxels/ChunksStorage.h"
|
#include "../voxels/ChunksStorage.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../physics/PhysicsSolver.h"
|
|
||||||
#include "../window/Camera.h"
|
#include "../window/Camera.h"
|
||||||
#include "../world/LevelEvents.h"
|
|
||||||
|
|
||||||
using glm::vec3;
|
using glm::vec3;
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
|
using std::string;
|
||||||
|
using std::filesystem::path;
|
||||||
|
|
||||||
World::World(std::string name, std::filesystem::path directory, int seed, EngineSettings& settings) : name(name), seed(seed) {
|
World::World(string name,
|
||||||
wfile = new WorldFiles(directory, REGION_VOL * (CHUNK_DATA_LEN * 2 + 8), settings.debug.generatorTestMode);
|
path directory,
|
||||||
|
uint64_t seed,
|
||||||
|
EngineSettings& settings)
|
||||||
|
: name(name), seed(seed) {
|
||||||
|
wfile = new WorldFiles(directory, settings.debug.generatorTestMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
World::~World(){
|
World::~World(){
|
||||||
@@ -34,18 +38,20 @@ void World::write(Level* level, bool writeChunks) {
|
|||||||
wfile->put(chunk.get());
|
wfile->put(chunk.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
wfile->write();
|
wfile->write(WorldInfo {name, wfile->directory, seed});
|
||||||
wfile->writePlayer(level->player);
|
wfile->writePlayer(level->player);
|
||||||
}
|
}
|
||||||
|
|
||||||
Level* World::loadLevel(EngineSettings& settings) {
|
Level* World::load(EngineSettings& settings) {
|
||||||
ChunksStorage* storage = new ChunksStorage();
|
WorldInfo info {name, wfile->directory, seed};
|
||||||
LevelEvents* events = new LevelEvents();
|
wfile->readWorldInfo(info);
|
||||||
|
seed = info.seed;
|
||||||
|
name = info.name;
|
||||||
|
|
||||||
vec3 playerPosition = vec3(0, 64, 0);
|
vec3 playerPosition = vec3(0, 64, 0);
|
||||||
Camera* camera = new Camera(playerPosition, glm::radians(90.0f));
|
Camera* camera = new Camera(playerPosition, glm::radians(90.0f));
|
||||||
Player* player = new Player(playerPosition, 4.0f, camera);
|
Player* player = new Player(playerPosition, 4.0f, camera);
|
||||||
Level* level = new Level(this, player, storage, events, settings);
|
Level* level = new Level(this, player, settings);
|
||||||
wfile->readPlayer(player);
|
wfile->readPlayer(player);
|
||||||
|
|
||||||
camera->rotation = mat4(1.0f);
|
camera->rotation = mat4(1.0f);
|
||||||
|
|||||||
+6
-3
@@ -15,13 +15,16 @@ class World {
|
|||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
WorldFiles* wfile;
|
WorldFiles* wfile;
|
||||||
int seed;
|
uint64_t seed;
|
||||||
|
|
||||||
World(std::string name, std::filesystem::path directory, int seed, EngineSettings& settings);
|
World(std::string name,
|
||||||
|
std::filesystem::path directory,
|
||||||
|
uint64_t seed,
|
||||||
|
EngineSettings& settings);
|
||||||
~World();
|
~World();
|
||||||
|
|
||||||
void write(Level* level, bool writeChunks);
|
void write(Level* level, bool writeChunks);
|
||||||
Level* loadLevel(EngineSettings& settings);
|
Level* load(EngineSettings& settings);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* WORLD_WORLD_H_ */
|
#endif /* WORLD_WORLD_H_ */
|
||||||
Reference in New Issue
Block a user