aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SOURCES15
-rw-r--r--src/globals.h1
-rw-r--r--src/obj.c3
-rw-r--r--src/server.c83
-rw-r--r--src/world.c21
-rw-r--r--src/world.h16
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>
diff --git a/src/obj.c b/src/obj.c
index ce4a890..c842d70 100644
--- a/src/obj.c
+++ b/src/obj.c
@@ -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);