diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/SOURCES | 15 | ||||
| -rw-r--r-- | src/globals.h | 1 | ||||
| -rw-r--r-- | src/obj.c | 3 | ||||
| -rw-r--r-- | src/server.c | 83 | ||||
| -rw-r--r-- | src/world.c | 21 | ||||
| -rw-r--r-- | src/world.h | 16 |
6 files changed, 115 insertions, 24 deletions
diff --git a/src/SOURCES b/src/SOURCES new file mode 100644 index 0000000..5cb3c9b --- /dev/null +++ b/src/SOURCES @@ -0,0 +1,15 @@ +auth.c +client.c +client_reqs.c +hash.c +main.c +multimap.c +obj.c +room.c +server.c +server_reqs.c +telnet.c +userdb.c +util.c +verb.c +world.c diff --git a/src/globals.h b/src/globals.h index 193bed4..6e050ee 100644 --- a/src/globals.h +++ b/src/globals.h @@ -30,6 +30,7 @@ #include <arpa/telnet.h> #include <assert.h> #include <ctype.h> +#include <dlfcn.h> #include <errno.h> #include <fcntl.h> #include <inttypes.h> @@ -21,6 +21,7 @@ #include "hash.h" #include "multimap.h" #include "obj.h" +#include "world.h" /* map of class names -> object classes */ static void *obj_class_map = NULL; @@ -41,8 +42,6 @@ struct object_t *obj_new(const char *class_name) { if(!obj_class_map) { - extern const struct obj_class_t netcosm_obj_classes[]; - extern const size_t netcosm_obj_classes_sz; obj_class_map = hash_init(netcosm_obj_classes_sz / 2 + 1, hash_djb, compare_strings); diff --git a/src/server.c b/src/server.c index a4558bc..55cb1f3 100644 --- a/src/server.c +++ b/src/server.c @@ -41,6 +41,8 @@ static uint16_t port = DEFAULT_PORT; static int server_socket; +static char *world_module = "build/worlds/netcosm_default.so"; + #define SAVE_INTERVAL 10 /* saves state periodically */ @@ -179,10 +181,28 @@ static void check_userfile(void) static void load_worldfile(void) { - extern const struct roomdata_t netcosm_world[]; - extern const size_t netcosm_world_sz; + /* load the world module */ + void *handle = dlopen(world_module, RTLD_NOW); + if(!handle) + error("cannot load world module `%s' (%s)", world_module, dlerror()); + + /* load symbols */ + size_t *ptr; + + netcosm_verb_classes = dlsym(handle, "netcosm_verb_classes"); + ptr = dlsym(handle, "netcosm_verb_classes_sz"); + netcosm_verb_classes_sz = *ptr; - extern const char *netcosm_world_name; + netcosm_obj_classes = dlsym(handle, "netcosm_obj_classes"); + ptr = dlsym(handle, "netcosm_obj_classes_sz"); + netcosm_obj_classes_sz = *ptr; + + netcosm_world = dlsym(handle, "netcosm_world"); + ptr = dlsym(handle, "netcosm_world_sz"); + netcosm_world_sz = *ptr; + + char **tmp = dlsym(handle, "netcosm_world_name"); + netcosm_world_name = *tmp; if(access(WORLDFILE, F_OK) < 0) { @@ -375,6 +395,21 @@ static void init_signals(void) error("sigaction"); } +static void __attribute__((noreturn)) print_help(char *argv[]) +{ + debugf("Usage: %s [OPTION]...\n", argv[0]); + debugf("NetCosm MUD server\n"); + debugf("\n"); + debugf(" -a USER PASS\tautomatic setup with USER/PASS\n"); + debugf(" -d PREFIX\tcreate and change to PREFIX before writing data files\n"); + debugf(" -h, -?\t\tshow this help\n"); + debugf(" -p PORT\tlisten on PORT\n"); + debugf(" -w MODULE\tuse a different world module\n"); + exit(0); +} + +static char *data_prefix = NULL; + static void parse_args(int argc, char *argv[]) { for(int i = 1; i < argc; ++i) @@ -388,20 +423,29 @@ static void parse_args(int argc, char *argv[]) switch(c) { case 'h': /* help */ - debugf("Usage: %s [-d PREFIX] [-a <username> <password>]\n", argv[0]); - exit(0); + case '?': + print_help(argv); case 'a': /* automatic first-run config */ autoconfig = true; + if(i + 2 > argc) + print_help(argv); autouser = argv[++i]; autopass = argv[++i]; break; case 'd': /* set data prefix */ - mkdir(argv[++i], 0700); - if(chdir(argv[i]) < 0) - { - debugf("Cannot access data prefix.\n"); - exit(0); - } + if(i + 1 > argc) + print_help(argv); + data_prefix = argv[++i]; + break; + case 'p': /* set port */ + if(i + 1 > argc) + print_help(argv); + port = strtol(argv[++i], NULL, 10); + break; + case 'w': /* world */ + if(i + 1 > argc) + print_help(argv); + world_module = argv[++i]; break; default: c = 'h'; @@ -409,8 +453,6 @@ static void parse_args(int argc, char *argv[]) } } } - else - port = strtol(argv[i], NULL, 10); } } @@ -431,13 +473,24 @@ int server_main(int argc, char *argv[]) parse_args(argc, argv); + /* this must be done before any world module data is used */ + load_worldfile(); + + if(data_prefix) + { + mkdir(data_prefix, 0700); + if(chdir(data_prefix) < 0) + { + debugf("Cannot access data prefix.\n"); + exit(0); + } + } + userdb_init(USERFILE); /* also performs first-time setup: */ check_userfile(); - load_worldfile(); - /* initialize request map */ reqmap_init(); diff --git a/src/world.c b/src/world.c index b3bb4b3..d7c3590 100644 --- a/src/world.c +++ b/src/world.c @@ -23,6 +23,20 @@ #include "room.h" #include "world.h" +/* verb classes */ +const struct verb_class_t *netcosm_verb_classes; +size_t netcosm_verb_classes_sz; + +/* object classes */ +const struct obj_class_t *netcosm_obj_classes; +size_t netcosm_obj_classes_sz; + +/* rooms */ +const struct roomdata_t *netcosm_world; +size_t netcosm_world_sz; + +const char *netcosm_world_name; + /* processed world data */ static struct room_t *world; @@ -184,7 +198,10 @@ bool world_load(const char *fname, const struct roomdata_t *data, size_t data_sz read(fd, &world_sz, sizeof(world_sz)); if(world_sz != data_sz) + { + debugf("Incompatible world state.\n"); return false; + } world = calloc(world_sz, sizeof(struct room_t)); @@ -192,10 +209,12 @@ bool world_load(const char *fname, const struct roomdata_t *data, size_t data_sz if(strcmp(name, world_name)) { free(world_name); - debugf("Incompatible world state.\n"); + debugf("Incompatible world state (%s %s).\n", name, world_name); return false; } + debugf("Loading world `%s'.\n", world_name); + obj_set_idcounter(1); size_t n_global_verbs = read_size(fd); diff --git a/src/world.h b/src/world.h index 50f9769..5dcd85d 100644 --- a/src/world.h +++ b/src/world.h @@ -26,19 +26,23 @@ /* the world module MUST define all of the following: */ +#ifndef _WORLD_MODULE_ +/* note that these are now dynamically loaded */ + /* verb classes */ -extern const struct verb_class_t netcosm_verb_classes[]; -extern const size_t netcosm_verb_classes_sz; +extern const struct verb_class_t *netcosm_verb_classes; +extern size_t netcosm_verb_classes_sz; /* object classes */ -extern const struct obj_class_t netcosm_obj_classes[]; -extern const size_t netcosm_obj_classes_sz; +extern const struct obj_class_t *netcosm_obj_classes; +extern size_t netcosm_obj_classes_sz; /* rooms */ -extern const struct roomdata_t netcosm_world[]; -extern const size_t netcosm_world_sz; +extern const struct roomdata_t *netcosm_world; +extern size_t netcosm_world_sz; extern const char *netcosm_world_name; +#endif /*** loads the world into RAM for the first time, resets the game state ***/ void world_init(const struct roomdata_t *data, size_t sz, const char *name); |