Add MapBlock serialisation buffer

master
Elias Fleckenstein 2021-03-29 22:36:04 +02:00
parent f6d58716f6
commit d224eeb5bf
5 changed files with 72 additions and 32 deletions

View File

@ -1,5 +1,7 @@
# Dragonblocks alpha
A multiplayer voxelgame for POSIX.1-2008 systems.
## Usage
```bash
./DragonblocksServer <port>

View File

@ -3,6 +3,7 @@
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include <endian.h>
#include "map.h"
#include "util.h"
@ -128,13 +129,18 @@ bool map_deserialize_node(int fd, MapNode *node)
return true;
}
bool map_serialize_block(int fd, MapBlock *block)
bool map_serialize_block(FILE *file, MapBlock *block)
{
if (! write_v3s32(fd, block->pos))
s32 pos[3] = {
htobe32(block->pos.x),
htobe32(block->pos.y),
htobe32(block->pos.z),
};
if (fwrite(pos, 1, sizeof(pos), file) != sizeof(pos))
return false;
if (write(fd, block->data, sizeof(block->data)) == -1)
perror("write");
if (fwrite(block->data, 1, sizeof(block->data), file) != sizeof(block->data))
perror("fwrite");
else
return true;
@ -192,13 +198,13 @@ bool map_deserialize_block(int fd, Map *map, MapBlock **blockptr, bool dummy)
return ret;
}
bool map_serialize(int fd, Map *map)
bool map_serialize(FILE *file, Map *map)
{
for (size_t s = 0; s < map->sectors.siz; s++) {
MapSector *sector = map_get_sector_raw(map, s);
for (size_t b = 0; b < sector->blocks.siz; b++)
if (! map_serialize_block(fd, map_get_block_raw(sector, b)))
return false;
if (! map_serialize_block(file, map_get_block_raw(sector, b)))
return true;
}
return true;
}

View File

@ -57,9 +57,9 @@ MapBlock *map_get_block(Map *map, v3s32 pos, bool create);
void map_free_block(MapBlock *block);
bool map_deserialize_node(int fd, MapNode *buf);
bool map_serialize_block(int fd, MapBlock *block);
bool map_serialize_block(FILE *file, MapBlock *block);
bool map_deserialize_block(int fd, Map *map, MapBlock **blockptr, bool dummy);
bool map_serialize(int fd, Map *map);
bool map_serialize(FILE *file, Map *map);
void map_deserialize(int fd, Map *map);
v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset);

View File

@ -106,7 +106,7 @@ void server_start(int fd)
mapfile = fopen("map", "w");
if (mapfile) {
if (map_serialize(fileno(mapfile), server.map))
if (map_serialize(mapfile, server.map))
printf("Saved map\n");
else
perror("map_serialize");

View File

@ -1,4 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <perlin/perlin.h>
#include "servermap.h"
@ -36,6 +39,32 @@ static void generate_block(MapBlock *block)
block->state = MBS_READY;
}
typedef struct
{
char *ptr;
size_t size;
} MapBlockBuffer;
static void serialize_block(Client *client, MapBlock *block)
{
MapBlockBuffer *buffer = block->extra;
if (! buffer) {
buffer = malloc(sizeof(MapBlockBuffer));
FILE *buffile = open_memstream(&buffer->ptr, &buffer->size);
map_serialize_block(buffile, block);
fflush(buffile);
fclose(buffile);
block->extra = buffer;
}
pthread_mutex_lock(&client->mtx);
(void) (write_u32(client->fd, CC_BLOCK) && write(client->fd, buffer->ptr, buffer->size) != -1);
pthread_mutex_unlock(&client->mtx);
}
static void send_block(MapBlock *block)
{
pthread_mutex_lock(&block->mtx);
@ -45,11 +74,8 @@ static void send_block(MapBlock *block)
if (block->state != MBS_READY)
break;
Client *client = pair->value;
if (client->state == CS_ACTIVE) {
pthread_mutex_lock(&client->mtx);
(void) (write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, block));
pthread_mutex_unlock(&client->mtx);
}
if (client->state == CS_ACTIVE)
serialize_block(client, block);
}
pthread_mutex_unlock(&block->mtx);
}
@ -59,7 +85,7 @@ static void send_block(MapBlock *block)
static size_t pos_chache_count = POS_CACHE_COUNT;
static v3s32 pos_cache[POS_CACHE_COUNT];
static void create_pos_cache()
static void init_pos_cache()
{
size_t i = -1;
#define ADDPOS(a, b, c, va, vb, vc) \
@ -107,21 +133,27 @@ static void send_blocks(Client *client, bool init)
v3s32 pos = map_node_to_block_pos((v3s32) {client->pos.x, client->pos.y, client->pos.z}, NULL);
for (size_t i = 0; i < pos_chache_count; i++) {
MapBlock *block = map_get_block(client->server->map, (v3s32) {pos.x + pos_cache[i].x, pos.y + pos_cache[i].y, pos.z + pos_cache[i].z}, ! init);
if (init)
(void) (block && write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, block));
else switch (block->state) {
case MBS_CREATED:
generate_block(block);
__attribute__ ((fallthrough));
case MBS_MODIFIED:
send_block(block);
__attribute__ ((fallthrough));
case MBS_PROCESSING:
i = -1;
sched_yield();
__attribute__ ((fallthrough));
case MBS_READY:
break;
if (init) {
if (block)
serialize_block(client, block);
} else switch (block->state) {
case MBS_CREATED:
generate_block(block);
__attribute__ ((fallthrough));
case MBS_MODIFIED:
if (block->extra) {
free(((MapBlockBuffer *) block->extra)->ptr);
free(block->extra);
block->extra = NULL;
}
send_block(block);
__attribute__ ((fallthrough));
case MBS_PROCESSING:
i = -1;
sched_yield();
__attribute__ ((fallthrough));
case MBS_READY:
break;
}
}
}
@ -141,7 +173,7 @@ static void *block_send_thread(void *cli)
void servermap_init(Server *srv)
{
server = srv;
create_pos_cache();
init_pos_cache();
}
void servermap_add_client(Client *client)