Server tile type registry
This commit is contained in:
parent
05ae5bb258
commit
b119dbc129
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ all: server
|
|||
$(BUILD_DIR)/common/util/thread.o: $(BUILD_DIR)/common/util/thread.std.o
|
||||
cp $< $@
|
||||
|
||||
server: $(BUILD_DIR)/server/main.o $(BUILD_DIR)/common/util/hash_table.o $(BUILD_DIR)/common/util/byte_stream.o $(BUILD_DIR)/common/util/thread.o
|
||||
server: $(BUILD_DIR)/server/main.o $(BUILD_DIR)/server/world.o $(BUILD_DIR)/common/world.o $(BUILD_DIR)/common/util/hash_table.o $(BUILD_DIR)/common/util/byte_stream.o $(BUILD_DIR)/common/util/thread.o
|
||||
$(COMPILE_EXE)
|
||||
|
||||
run: server
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include "world.h"
|
||||
|
||||
void
|
||||
tile_type_forward_init_interned(TileTypeForwardInternation *reg)
|
||||
{
|
||||
if (!reg) {
|
||||
return;
|
||||
}
|
||||
hash_table_init(®->table, NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
tile_type_forward_intern_as(TileTypeForwardInternation *reg, const char *name, TileTypeId id)
|
||||
{
|
||||
if (!reg) {
|
||||
return false;
|
||||
}
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
HashTableIndex idx = hash_table_insert(®->table, hash_table_key_from_cstr(name), &id);
|
||||
return idx >= 0;
|
||||
}
|
||||
|
||||
bool
|
||||
tile_type_forward_get_interned(TileTypeForwardInternation *reg, const char *name, TileTypeId *outptr)
|
||||
{
|
||||
if (!reg) {
|
||||
return false;
|
||||
}
|
||||
HashTableIndex idx = hash_table_find(®->table, hash_table_key_from_cstr(name));
|
||||
if (idx < 0) {
|
||||
return false;
|
||||
}
|
||||
if (outptr) {
|
||||
*outptr = reg->table.value_array[idx];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
tile_type_forward_delete_interned(TileTypeForwardInternation *reg, const char *name)
|
||||
{
|
||||
if (!reg) {
|
||||
return false;
|
||||
}
|
||||
return hash_table_delete_by_key(®->table, hash_table_key_from_cstr(name));
|
||||
}
|
||||
|
||||
void
|
||||
tile_type_forward_clear_interned(TileTypeForwardInternation *reg)
|
||||
{
|
||||
if (!reg) {
|
||||
return;
|
||||
}
|
||||
hash_table_deinit(®->table);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef COMMON_WORLD_H_
|
||||
#define COMMON_WORLD_H_
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "common/util/hash_table.h"
|
||||
|
||||
typedef uint16_t TileTypeId;
|
||||
typedef uint16_t TileVariant;
|
||||
|
||||
typedef struct {
|
||||
TYPED_HASH_TABLE(TileTypeId) table;
|
||||
} TileTypeForwardInternation;
|
||||
|
||||
void tile_type_forward_init_interned(TileTypeForwardInternation *reg);
|
||||
bool tile_type_forward_intern_as(TileTypeForwardInternation *reg, const char *name, TileTypeId id);
|
||||
bool tile_type_forward_get_interned(TileTypeForwardInternation *reg, const char *name, TileTypeId *outptr);
|
||||
bool tile_type_forward_delete_interned(TileTypeForwardInternation *reg, const char *name);
|
||||
void tile_type_forward_clear_interned(TileTypeForwardInternation *reg);
|
||||
|
||||
#endif /* end of include guard: COMMON_WORLD_H_ */
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef SERVER_CLIENT_CONNECTION_H_
|
||||
#define SERVER_CLIENT_CONNECTION_H_
|
||||
|
||||
#include "common/defs.h"
|
||||
|
||||
typedef struct {
|
||||
uint64_t id;
|
||||
} ServerClientConnection;
|
||||
|
||||
#endif /* end of include guard: SERVER_CLIENT_CONNECTION_H_ */
|
|
@ -5,6 +5,7 @@
|
|||
#include "common/util/byte_serdes.h"
|
||||
#include "common/util/thread.h"
|
||||
#include "common/util/spin_lock.h"
|
||||
#include "server/world.h"
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
@ -12,5 +13,28 @@ main(int argc, char **argv)
|
|||
(void) argc;
|
||||
(void) argv;
|
||||
printf("Hello, server!\n");
|
||||
server_init_tile_type_registry();
|
||||
const char *name = "core:example";
|
||||
const char *name2 = "core:example2";
|
||||
ServerTileType example = {
|
||||
.name = name,
|
||||
.on_deregister = NULL,
|
||||
.read_tile = NULL,
|
||||
.write_tile = NULL,
|
||||
.send_tile = NULL,
|
||||
};
|
||||
TileTypeId example_id, example2_id, check_id;
|
||||
assert(server_register_tile_type(&example, &example_id));
|
||||
example.name = name2;
|
||||
assert(server_register_tile_type(&example, &example2_id));
|
||||
printf("%s registered as %d\n", name, example_id);
|
||||
printf("%s registered as %d\n", name2, example2_id);
|
||||
assert(server_tile_type_by_id(example_id)->name == name);
|
||||
assert(server_tile_type_by_id(example2_id)->name == name2);
|
||||
server_tile_id_by_name(name, &check_id);
|
||||
assert(check_id == example_id);
|
||||
server_tile_id_by_name(name2, &check_id);
|
||||
assert(check_id == example2_id);
|
||||
server_deinit_tile_type_registry();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
#include "world.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "common/util/spin_lock.h"
|
||||
|
||||
TileTypeId next_id = 0;
|
||||
TileTypeForwardInternation server_tile_type_internation;
|
||||
TYPED_HASH_TABLE(ServerTileType) server_tile_type_registry;
|
||||
SpinLock lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static void deinit_tile_type(ServerTileType *tile_type) __attribute__((nothrow));
|
||||
void
|
||||
deinit_tile_type(ServerTileType *tile_type)
|
||||
{
|
||||
if (!tile_type) {
|
||||
return;
|
||||
}
|
||||
if (!tile_type->on_deregister) {
|
||||
return;
|
||||
}
|
||||
tile_type->on_deregister(tile_type);
|
||||
}
|
||||
|
||||
void
|
||||
server_init_tile_type_registry()
|
||||
{
|
||||
spin_lock_acquire(&lock);
|
||||
tile_type_forward_init_interned(&server_tile_type_internation);
|
||||
hash_table_init(&server_tile_type_registry, &deinit_tile_type);
|
||||
spin_lock_release(&lock);
|
||||
}
|
||||
|
||||
void
|
||||
server_deinit_tile_type_registry()
|
||||
{
|
||||
spin_lock_acquire(&lock);
|
||||
hash_table_deinit(&server_tile_type_registry);
|
||||
tile_type_forward_clear_interned(&server_tile_type_internation);
|
||||
next_id = 0;
|
||||
spin_lock_release(&lock);
|
||||
}
|
||||
|
||||
bool
|
||||
server_register_tile_type(const ServerTileType *tile_type, TileTypeId *outptr)
|
||||
{
|
||||
if (!tile_type) {
|
||||
return false;
|
||||
}
|
||||
const char *name = tile_type->name;
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
spin_lock_acquire(&lock);
|
||||
TileTypeId id = next_id;
|
||||
HashTableKey id_key = hash_table_key_from_bytes((void*) &id, sizeof(id));
|
||||
if (hash_table_find(&server_tile_type_registry, id_key) >= 0) {
|
||||
for(++id; id != next_id; ++id) {
|
||||
if (hash_table_find(&server_tile_type_registry, (id_key = hash_table_key_from_bytes((void*) &id, sizeof(id)))) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id == next_id) {
|
||||
spin_lock_release(&lock);
|
||||
return false; // Ran out of ids
|
||||
}
|
||||
}
|
||||
next_id = id;
|
||||
if (!tile_type_forward_intern_as(&server_tile_type_internation, name, id)) {
|
||||
spin_lock_release(&lock);
|
||||
return false;
|
||||
}
|
||||
if (hash_table_insert(&server_tile_type_registry, id_key, tile_type) < 0) {
|
||||
tile_type_forward_delete_interned(&server_tile_type_internation, name);
|
||||
spin_lock_release(&lock);
|
||||
return false;
|
||||
}
|
||||
*outptr = id;
|
||||
++next_id;
|
||||
spin_lock_release(&lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
server_deregister_tile_type(TileTypeId id)
|
||||
{
|
||||
spin_lock_acquire(&lock);
|
||||
HashTableKey id_key = hash_table_key_from_bytes((void*) &id, sizeof(id));
|
||||
HashTableIndex reg_idx = hash_table_find(&server_tile_type_registry, id_key);
|
||||
if (reg_idx < 0) {
|
||||
spin_lock_release(&lock);
|
||||
return false;
|
||||
}
|
||||
const char *name = server_tile_type_registry.value_array[reg_idx].name;
|
||||
assert(name != NULL);
|
||||
tile_type_forward_delete_interned(&server_tile_type_internation, name);
|
||||
hash_table_delete_at_index(&server_tile_type_registry, reg_idx);
|
||||
spin_lock_release(&lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
server_tile_id_by_name(const char *name, TileTypeId *outptr)
|
||||
{
|
||||
spin_lock_acquire(&lock);
|
||||
bool result = tile_type_forward_get_interned(&server_tile_type_internation, name, outptr);
|
||||
spin_lock_release(&lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
const ServerTileType*
|
||||
server_tile_type_by_id(TileTypeId id)
|
||||
{
|
||||
spin_lock_acquire(&lock);
|
||||
HashTableKey id_key = hash_table_key_from_bytes((void*) &id, sizeof(id));
|
||||
HashTableIndex reg_idx = hash_table_find(&server_tile_type_registry, id_key);
|
||||
if (reg_idx < 0) {
|
||||
spin_lock_release(&lock);
|
||||
return NULL;
|
||||
}
|
||||
const ServerTileType *tile_type = &server_tile_type_registry.value_array[reg_idx];
|
||||
spin_lock_release(&lock);
|
||||
return tile_type;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef SERVER_WORLD_H_
|
||||
#define SERVER_WORLD_H_
|
||||
|
||||
#include "common/world.h"
|
||||
#include "common/util/byte_stream.h"
|
||||
#include "common/util/hash_table.h"
|
||||
#include "server/client_connection.h"
|
||||
|
||||
typedef struct server_tile_complex_data ServerTileComplexData;
|
||||
struct server_tile_complex_data {
|
||||
void (*destroy)(ServerTileComplexData *self); // Calls free
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
TileTypeId type;
|
||||
TileVariant variant;
|
||||
ServerTileComplexData *complex_data;
|
||||
} ServerTile;
|
||||
|
||||
// Relocateable
|
||||
typedef struct server_tile_type ServerTileType;
|
||||
struct server_tile_type {
|
||||
const char *name;
|
||||
void (*on_deregister)(const ServerTileType *self) __attribute__((nothrow));
|
||||
ServerTile (*read_tile)(AbstractInputByteStream *stream); // Full data
|
||||
void (*write_tile)(AbstractOutputByteStream *stream, ServerTile tile); // Full data
|
||||
void (*send_tile)(AbstractOutputByteStream *stream, ServerClientConnection *client, ServerTile tile); // Client data
|
||||
// Behavior handlers go here
|
||||
};
|
||||
|
||||
void server_init_tile_type_registry();
|
||||
void server_deinit_tile_type_registry();
|
||||
bool server_register_tile_type(const ServerTileType *tile_type, TileTypeId *outptr); // Relocates tile_type
|
||||
bool server_deregister_tile_type(TileTypeId id);
|
||||
bool server_tile_id_by_name(const char *name, TileTypeId *outptr);
|
||||
const ServerTileType *server_tile_type_by_id(TileTypeId id); // FIXME ensure thread safety?
|
||||
|
||||
#endif /* end of include guard: SERVER_WORLD_H_ */
|
Loading…
Reference in New Issue