Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lib/include/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,12 @@ namespace konstructs {
void send_string(const string &str);
size_t recv_all(char* out_buf, const size_t size);
void process_error(Packet *packet);
void process_chunk(Packet *packet);
void process_chunk(Packet *packet, char *inflation_buffer);
void process_chunk_updated(Packet *packet);
void cache_chunk(Vector3i pos, Packet *packet);
std::string cached_chunk_path(Vector3i pos);
bool is_chunk_cached(Vector3i pos);
void load_cached_chunk(Vector3i pos, char* inflation_buffer);
void recv_worker();
void send_worker();
bool is_empty_chunk(Vector3i pos);
Expand All @@ -113,7 +117,6 @@ namespace konstructs {
bool connected;
bool logged_in;
std::string error_message;
char *inflation_buffer;
/* Chunk worker */
Vector3i player_chunk;
int radius;
Expand Down
1 change: 1 addition & 0 deletions lib/include/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ GLuint gen_faces(int components, int faces, GLfloat *data);
void load_png_texture(const char *file_name);
void load_png_texture_from_buffer(const char *in, int size);
int file_exist(const char *filename);
bool make_dir(const char *filename);

#endif
96 changes: 79 additions & 17 deletions lib/src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
#include <string.h>
#include <errno.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <chrono>
#include <functional>
#include "client.h"
#include "util.h"

#define PROTOCOL_VERSION 8
#define MAX_RECV_SIZE 4096*1024
Expand All @@ -34,7 +37,6 @@ namespace konstructs {
recv_thread = new std::thread(&Client::recv_worker, this);
send_thread = new std::thread(&Client::send_worker, this);
chunk_thread = new std::thread(&Client::chunk_worker, this);
inflation_buffer = new char[BLOCK_BUFFER_SIZE];
}

string Client::get_error_message() {
Expand Down Expand Up @@ -109,7 +111,7 @@ namespace konstructs {
force_close();
}

void Client::process_chunk(Packet *packet) {
void Client::process_chunk(Packet *packet, char *inflation_buffer) {
int p, q, k;
char *pos = packet->buffer();

Expand All @@ -124,14 +126,62 @@ namespace konstructs {

Vector3i position(p, q, k);
received_chunk(position);
cache_chunk(position, packet);
const int blocks_size = packet->size - 3 * sizeof(int);
auto chunk = make_shared<ChunkData>(position, pos, blocks_size, (uint8_t*)inflation_buffer);
std::lock_guard<std::mutex> lock_packets(packets_mutex);
chunks.push_back(chunk);
}

/* Write a chunk to local disk cache */
void Client::cache_chunk(Vector3i pos, Packet *packet) {
std::string p_path = "cache/chunk/" + std::to_string(pos[0]);
std::string q_path = p_path + "/" + std::to_string(pos[1]);
std::string k_path = q_path + "/" + std::to_string(pos[2]);

if (!file_exist("cache")) make_dir("cache");
if (!file_exist("cache/chunk")) make_dir("cache/chunk");
if (!file_exist(p_path.c_str())) make_dir(p_path.c_str());
if (!file_exist(q_path.c_str())) make_dir(q_path.c_str());

ofstream cf(k_path, ofstream::binary);
cf.write(packet->buffer(),packet->size);
cf.close();
}

std::string Client::cached_chunk_path(Vector3i pos) {
stringstream cache_path;
cache_path << "cache/chunk/" << pos[0] << "/" << pos[1] << "/" << pos[2];

return cache_path.str();
}

bool Client::is_chunk_cached(Vector3i pos) {
return file_exist(cached_chunk_path(pos).c_str());
}

void Client::load_cached_chunk(Vector3i pos, char* inflation_buffer) {
string path(cached_chunk_path(pos));

// Get size of file
ifstream cf(path, ofstream::binary);
cf.seekg(0,cf.end);
long size = cf.tellg();
cf.seekg(0);

// make a package
auto packet = make_shared<Packet>('C', size);

// load the files content
cf.read(packet->buffer(), size);
cf.close();

process_chunk(packet.get(), inflation_buffer);
}

void Client::recv_worker() {
std::cout<<"[Recv worker]: started"<<std::endl;
char *inflation_buffer = new char[BLOCK_BUFFER_SIZE];
while(1) {
try {
std::cout<<"[Recv worker]: waiting for connection"<<std::endl;
Expand Down Expand Up @@ -163,7 +213,7 @@ namespace konstructs {
int r = recv_all(packet->buffer(), packet->size);
// move data over to packet_buffer
if(packet->type == 'C')
process_chunk(packet.get());
process_chunk(packet.get(), inflation_buffer);
else if(packet->type == 'E')
process_error(packet.get());
else if(packet->type == 'c')
Expand All @@ -174,6 +224,7 @@ namespace konstructs {
}
}
} catch(const std::exception& ex) {
delete[] inflation_buffer;
std::cout << "[Recv worker]: Caught exception: " << ex.what() << std::endl;
std::cout << "[Recv worker]: Will assume connection is down: " << ex.what() << std::endl;
error_message = "Disconnected from server.";
Expand Down Expand Up @@ -439,6 +490,7 @@ namespace konstructs {
bool chunk_changed = false; // Stores if the chunk the player is in changed
// Stores the chunks that needs to be fetched in priority order
priority_queue<ChunkToFetch, vector<ChunkToFetch>, LessThanByScore> chunks_to_fetch;
char *inflation_buffer = new char[BLOCK_BUFFER_SIZE];

while(connected && logged_in) {

Expand Down Expand Up @@ -508,12 +560,16 @@ namespace konstructs {
for(int q = -r - 1; q < r; q++) {
for(int k = -r - 1; k < r; k++) {
Vector3i pos = p_chunk + Vector3i(p, q, k);

if(is_empty_chunk(pos)) {
int distance = (pos - p_chunk).norm();
// This checks removes edges so that we request a sphere not a cube
if(distance <= r) {
// Add chunk to queue
int distance = (pos - p_chunk).norm();

// This checks removes edges so that we request a sphere not a cube
if(distance <= r) {
if(is_empty_chunk(pos) && is_chunk_cached(pos)) {
// Missing chunk, and we have the chunk cached on disk.
load_cached_chunk(pos, inflation_buffer);
set_loaded_radius(distance);
} else if(is_empty_chunk(pos)) {
// Request missing chunks with no local cache.
chunks_to_fetch.push({distance, pos});
}
}
Expand All @@ -532,14 +588,18 @@ namespace konstructs {
for(int q = -r - 1; q < r; q++) {
for(int k = -r - 1; k < r; k++) {
Vector3i pos = p_chunk + Vector3i(p, q, k);

if(is_empty_chunk(pos)) {
int distance = (pos - p_chunk).norm();

// This checks removes edges so that we request a sphere not a cube
// It also rejects chunks that was already previously added to the queue
// that is chunks within the old radius
if(distance <= r && distance >= old_r) {
int distance = (pos - p_chunk).norm();

// This checks removes edges so that we request a sphere not a cube
// It also rejects chunks that was already previously added to the queue
// that is chunks within the old radius
if(distance <= r && distance >= old_r) {
if(is_empty_chunk(pos) && is_chunk_cached(pos)) {
// Missing chunk, and we have the chunk cached on disk.
load_cached_chunk(pos, inflation_buffer);
set_loaded_radius(distance);
} else if(is_empty_chunk(pos)) {
// Request missing chunks with no local cache.
chunks_to_fetch.push({distance, pos});
}
}
Expand Down Expand Up @@ -607,6 +667,8 @@ namespace konstructs {
}
std::this_thread::sleep_for(std::chrono::milliseconds(15));
}

delete[] inflation_buffer;
}
}
};
5 changes: 5 additions & 0 deletions lib/src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,8 @@ int file_exist(const char *filename) {
int result = stat(filename, &st);
return result == 0;
}

// TODO: Will will not work under windows, I think ...
bool make_dir(const char *filename) {
return (mkdir(filename, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != -1);
}