#include <unistd.h>
#include <stdio.h>
#include <math.h>
+#include <endian.h>
#include "map.h"
#include "util.h"
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;
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;
}
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);
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
#include <perlin/perlin.h>
#include "servermap.h"
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);
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);
}
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) \
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;
}
}
}
void servermap_init(Server *srv)
{
server = srv;
- create_pos_cache();
+ init_pos_cache();
}
void servermap_add_client(Client *client)