aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--src/client.c14
-rw-r--r--src/globals.h1
-rw-r--r--src/room.c40
-rw-r--r--src/room.h24
-rw-r--r--src/server_reqs.c39
-rw-r--r--src/server_reqs.h1
-rw-r--r--src/util.c9
-rw-r--r--src/util.h1
9 files changed, 103 insertions, 29 deletions
diff --git a/README.md b/README.md
index af3fd84..81fdc34 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,8 @@ features might drift out of existence without prior warning!
### Prerequisites:
-* openssl
+* openssl (for password hashing)
+* libbsd (for arc4random, strlcpy, etc.)
* libev
* linux >= 3.4 (for "packet mode" pipes)
* glibc >= 2.9
diff --git a/src/client.c b/src/client.c
index fef7fab..260d73d 100644
--- a/src/client.c
+++ b/src/client.c
@@ -419,6 +419,12 @@ void client_look(void)
send_master(REQ_GETROOMDESC, NULL, 0);
}
+void client_look_at(char *obj)
+{
+ all_lower(obj);
+ send_master(REQ_LOOKAT, obj, strlen(obj) + 1);
+}
+
#define WSPACE " \t\r\n"
void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
@@ -689,7 +695,13 @@ auth:
}
else if(!strcmp(tok, "LOOK"))
{
- client_look();
+ char *what = strtok_r(NULL, " ", &save);
+ if(!what)
+ client_look();
+ else
+ {
+ client_look_at(what);
+ }
}
else if(!strcmp(tok, "WAIT"))
{
diff --git a/src/globals.h b/src/globals.h
index 9944996..fcf6784 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -29,6 +29,7 @@
#include <arpa/telnet.h>
#include <assert.h>
#include <bsd/stdlib.h> // for arc4random
+#include <bsd/string.h> // for strlcat
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
diff --git a/src/room.c b/src/room.c
index eaa8cf1..3e708f6 100644
--- a/src/room.c
+++ b/src/room.c
@@ -145,49 +145,36 @@ void world_free(void)
struct object_t *obj_new(void)
{
- struct object_t *new = calloc(1, sizeof(struct object_t));
+ struct object_t *obj = calloc(1, sizeof(struct object_t));
/* generate a unique 128-bit id for this object */
/* 64 bits are used to store a nanosecond-resolution timestamp */
/* 64 random bits are also used */
uint64_t timestamp;
struct timeval tv;
gettimeofday(&tv, NULL);
- timestamp = (obj_id)tv.tv_sec * (obj_id)1000000 + (obj_id)tv.tv_usec;
+ timestamp = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec;
uint64_t rand_bits;
arc4random_buf(&rand_bits, sizeof(rand_bits));
- new->id = ((obj_id)timestamp << 64) | (obj_id)rand_bits;
+ obj->id.halves[0] = timestamp;
+ obj->id.halves[1] = rand_bits;
- unsigned char bytes[16];
- memcpy(bytes, &new->id, sizeof(bytes));
- debugf("UUID: ");
- for(unsigned i = 0; i < sizeof(bytes); ++i)
- {
- if(i == 4 || i == 6 || i == 8 || i == 10)
- debugf("-");
- debugf("%02x", bytes[15 - i]);
- }
- debugf("\n");
-
- return new;
+ return obj;
}
bool obj_add(room_id room, struct object_t *obj)
{
- return !hash_insert(room_get(room)->objects, &obj->id, obj);
+ return !hash_insert(room_get(room)->objects, obj->name, obj);
}
-static SIMP_HASH(obj_id, obj_hash);
-static SIMP_EQUAL(obj_id, obj_equal);
-
#define OBJMAP_SIZE 8
/* initialize the room's hash tables */
static void room_init_maps(struct room_t *room)
{
room->users = hash_init((userdb_size() / 2) + 1, hash_djb, compare_strings);
- room->objects = hash_init(OBJMAP_SIZE, obj_hash, obj_equal);
+ room->objects = hash_init(OBJMAP_SIZE, hash_djb, compare_strings);
}
/**
@@ -349,3 +336,16 @@ void world_init(const struct roomdata_t *data, size_t sz, const char *name)
hash_free(map);
}
+
+struct object_t *room_obj_iterate(room_id room, void **save)
+{
+ if(room != ROOM_NONE)
+ return hash_iterate(room_get(room)->objects, save, NULL);
+ else
+ return hash_iterate(NULL, save, NULL);
+}
+
+struct object_t *room_obj_get(room_id room, const char *name)
+{
+ return hash_lookup(room_get(room)->objects, name);
+}
diff --git a/src/room.h b/src/room.h
index d0c1fdb..485e307 100644
--- a/src/room.h
+++ b/src/room.h
@@ -25,7 +25,11 @@
typedef enum room_id { ROOM_NONE = -1 } room_id;
-typedef unsigned __int128 obj_id;
+typedef struct int128 {
+ uint64_t halves[2];
+} int128;
+
+typedef int128 obj_id;
typedef struct child_data user_t;
@@ -58,7 +62,7 @@ struct object_t {
bool list;
void (*hook_serialize)(int fd, struct object_t*);
- void (*hook_take)(struct object_t*, user_t *user);
+ bool (*hook_take)(struct object_t*, user_t *user);
void (*hook_drop)(struct object_t*, user_t *user);
void (*hook_use)(struct object_t*, user_t *user);
void (*hook_destroy)(struct object_t*);
@@ -79,7 +83,7 @@ struct room_t {
room_id adjacent[NUM_DIRECTIONS];
/* hash maps */
- void *objects; /* obj_id -> object */
+ void *objects; /* object name -> object */
void *verbs;
void *users; /* username -> child_data */
};
@@ -96,7 +100,17 @@ bool room_user_del(room_id id, struct child_data *child);
/* returns a new object with a unique id */
struct object_t *obj_new(void);
-/* new should point to a new object allocated with obj_new */
-bool obj_add(room_id room, struct object_t *new);
+/* new should point to a new object allocated with obj_new(), with
+ * 'name' properly set */
+bool obj_add(room_id room, struct object_t *obj);
+
+/* on the first call, room should be a valid room id, and *save should
+ * point to a void pointer. On subsequent calls, room should be
+ * ROOM_NONE, and *save should remain unchanged from the previous
+ * call */
+struct object_t *room_obj_iterate(room_id room, void **save);
+
+/* obj should be all lowercase */
+struct object_t *room_obj_get(room_id room, const char *obj);
void world_free(void);
diff --git a/src/server_reqs.c b/src/server_reqs.c
index d10acde..7f82236 100644
--- a/src/server_reqs.c
+++ b/src/server_reqs.c
@@ -135,8 +135,25 @@ static void req_send_desc(unsigned char *data, size_t datalen, struct child_data
struct room_t *room = room_get(sender->room);
send_packet(sender, REQ_BCASTMSG, room->data.desc, strlen(room->data.desc));
-
send_packet(sender, REQ_PRINTNEWLINE, NULL, 0);
+
+ /* list objects */
+ char buf[MSG_MAX];
+ buf[0] = 0;
+ void *save = NULL;
+ room_id id = sender->room;
+ while(1)
+ {
+ struct object_t *obj = room_obj_iterate(id, &save);
+ id = ROOM_NONE;
+ if(!obj)
+ break;
+ strlcat(buf, "There is a(n) ", sizeof(buf));
+ strlcat(buf, obj->name, sizeof(buf));
+ strlcat(buf, " here.\n", sizeof(buf));
+ }
+
+ send_packet(sender, REQ_BCASTMSG, buf, strlen(buf));
}
static void req_send_roomname(unsigned char *data, size_t datalen, struct child_data *sender)
@@ -236,6 +253,23 @@ static void req_kick_always(unsigned char *data, size_t datalen,
send_packet(child, REQ_KICK, data, datalen);
}
+static void req_look_at(unsigned char *data, size_t datalen, struct child_data *sender)
+{
+ (void) datalen;
+ struct object_t *obj = room_obj_get(sender->room, (const char*)data);
+ if(obj)
+ {
+ const char *desc = obj->hook_desc(obj, sender);
+ send_packet(sender, REQ_BCASTMSG, (void*)desc, strlen(desc));
+ send_packet(sender, REQ_PRINTNEWLINE, NULL, 0);
+ }
+ else
+ {
+ const char *msg = "I don't know what that is.\n";
+ send_packet(sender, REQ_BCASTMSG, (void*)msg, strlen(msg));
+ }
+}
+
static const struct child_request {
unsigned char code;
@@ -264,7 +298,8 @@ static const struct child_request {
{ REQ_GETUSERDATA, true, CHILD_NONE, NULL, req_send_user, },
{ REQ_DELUSERDATA, true, CHILD_NONE, NULL, req_del_user, },
{ REQ_ADDUSERDATA, true, CHILD_NONE, NULL, req_add_user, },
- { REQ_KICKALL, true, CHILD_ALL_BUT_SENDER, req_kick_always, NULL },
+ { REQ_KICKALL, true, CHILD_ALL_BUT_SENDER, req_kick_always, NULL, },
+ { REQ_LOOKAT, true, CHILD_NONE, NULL, req_look_at, },
//{ REQ_ROOMMSG, true, CHILD_ALL, req_send_room_msg, NULL, },
};
diff --git a/src/server_reqs.h b/src/server_reqs.h
index 6ab093b..f148c3e 100644
--- a/src/server_reqs.h
+++ b/src/server_reqs.h
@@ -38,6 +38,7 @@
#define REQ_PRINTNEWLINE 16 /* child: print a newline */
#define REQ_ALLDONE 17 /* child: break out of send_master() */
#define REQ_KICKALL 18 /* server: kick everyone except the sender */
+#define REQ_LOOKAT 19 /* server: send object description */
/* child states, sent as an int to the master */
#define STATE_INIT 0 /* initial state */
diff --git a/src/util.c b/src/util.c
index 99a70c5..e681ca0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -57,3 +57,12 @@ void all_upper(char *s)
s++;
}
}
+
+void all_lower(char *s)
+{
+ while(*s)
+ {
+ *s = tolower(*s);
+ s++;
+ }
+}
diff --git a/src/util.h b/src/util.h
index 3d7287a..0f05a89 100644
--- a/src/util.h
+++ b/src/util.h
@@ -24,3 +24,4 @@ void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, ...);
void __attribute__((format(printf,4,5))) debugf_real(const char*, int, const char*, const char *fmt, ...);
void remove_cruft(char*);
void all_upper(char*);
+void all_lower(char*);