aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2016-03-24 21:45:47 -0400
committerFranklin Wei <git@fwei.tk>2016-03-24 21:45:47 -0400
commiteb8b5907df2cf3c4b593197d40d10e83e6943ee3 (patch)
treee19b5d3ee90e7d29b5975ad05496b2ab1385ad15 /src
parenta91f858ebaea0f403b2c59773e619086b9198a39 (diff)
downloadnetcosm-eb8b5907df2cf3c4b593197d40d10e83e6943ee3.zip
netcosm-eb8b5907df2cf3c4b593197d40d10e83e6943ee3.tar.gz
netcosm-eb8b5907df2cf3c4b593197d40d10e83e6943ee3.tar.bz2
netcosm-eb8b5907df2cf3c4b593197d40d10e83e6943ee3.tar.xz
fix for drop bug
Diffstat (limited to 'src')
-rw-r--r--src/globals.h1
-rw-r--r--src/hash.c4
-rw-r--r--src/main.c2
-rw-r--r--src/multimap.c14
-rw-r--r--src/obj.c8
-rw-r--r--src/obj.h28
-rw-r--r--src/room.c25
-rw-r--r--src/room.h13
-rw-r--r--src/server.c19
-rw-r--r--src/server.h22
-rw-r--r--src/server_reqs.c79
-rw-r--r--src/server_reqs.h6
-rw-r--r--src/userdb.c37
-rw-r--r--src/userdb.h4
-rw-r--r--src/verb.h3
-rw-r--r--src/world.c7
16 files changed, 190 insertions, 82 deletions
diff --git a/src/globals.h b/src/globals.h
index d26dc15..987d382 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -88,6 +88,7 @@
#include "util.h"
#define MSG_MAX PIPE_BUF
+
#ifndef NDEBUG
#define debugf(fmt,...) debugf_real(__func__, __LINE__, __FILE__, fmt, ##__VA_ARGS__)
#else
diff --git a/src/hash.c b/src/hash.c
index eed4846..59c05bf 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -308,12 +308,16 @@ bool hash_remove(void *ptr, const void *key)
last->next = iter->next;
else
map->table[hash] = iter->next;
+
if(map->free_key)
map->free_key((void*)iter->key);
if(map->free_data)
map->free_data((void*)iter->data);
+
--map->n_entries;
+
free(iter);
+
return true;
}
last = iter;
diff --git a/src/main.c b/src/main.c
index 3de3d89..b69ce76 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,4 +5,6 @@
int main(int argc, char *argv[])
{
server_main(argc, argv);
+
+ error("weird");
}
diff --git a/src/multimap.c b/src/multimap.c
index b958db0..033b511 100644
--- a/src/multimap.c
+++ b/src/multimap.c
@@ -193,11 +193,12 @@ size_t multimap_delete(void *ptr, const void *key, const void *val)
struct multimap_node *node = hash_lookup(map->hash_tab, key);
if(!node)
- return false;
+ return 0;
+
/* iterate over the node's pairs and delete */
size_t deleted = 0;
- struct multimap_list *last = NULL, *iter = node->list, *next;;
+ struct multimap_list *last = NULL, *iter = node->list, *next;
while(iter)
{
next = iter->next;
@@ -209,9 +210,10 @@ size_t multimap_delete(void *ptr, const void *key, const void *val)
map->free_key((void*)iter->key);
if(last)
- last->next = iter->next;
+ last->next = next;
else
- node->list = iter->next;
+ node->list = next;
+
free(iter);
++deleted;
@@ -251,7 +253,9 @@ size_t multimap_delete_all(void *ptr, const void *key)
return ret;
}
- /* fall through */
+
+ /* fall through on failure */
+
}
return 0;
}
diff --git a/src/obj.c b/src/obj.c
index 293aaff..deeb30d 100644
--- a/src/obj.c
+++ b/src/obj.c
@@ -67,7 +67,7 @@ struct object_t *obj_new(const char *class_name)
obj->id = idcounter++;
obj->refcount = 1;
- obj->list = true;
+ obj->hidden = false;
obj->default_article = true;
return obj;
@@ -80,7 +80,7 @@ void obj_write(int fd, struct object_t *obj)
write_uint64(fd, obj->id);
write_string(fd, obj->name);
- write_bool(fd, obj->list);
+ write_bool(fd, obj->hidden);
write_bool(fd, obj->default_article);
struct obj_alias_t *iter = obj->alias_list;
@@ -104,7 +104,7 @@ struct object_t *obj_read(int fd)
obj->id = read_uint64(fd);
obj->name = read_string(fd);
- obj->list = read_bool(fd);
+ obj->hidden = read_bool(fd);
obj->default_article = read_bool(fd);
/* aliases */
@@ -136,7 +136,7 @@ struct object_t *obj_copy(struct object_t *obj)
{
struct object_t *ret = obj_new(obj->class->class_name);
ret->name = strdup(obj->name);
- ret->list = obj->list;
+ ret->hidden = obj->hidden;
if(obj->class->hook_dupdata)
ret->userdata = obj->class->hook_dupdata(obj);
return ret;
diff --git a/src/obj.h b/src/obj.h
index 249f9c1..121e3ab 100644
--- a/src/obj.h
+++ b/src/obj.h
@@ -27,9 +27,9 @@
* internally.
*/
-struct object_t;
+typedef struct child_data user_t;
-typedef struct child_data user_t; // see server.h for the definition
+struct object_t;
struct obj_class_t {
const char *class_name;
@@ -46,11 +46,6 @@ struct obj_class_t {
* no function (NULL) = can take */
bool (*hook_take)(struct object_t*, user_t *user);
- /* called when dropping an object;
- * true: can drop
- * false: can't drop
- * NULL: can drop
- */
bool (*hook_drop)(struct object_t*, user_t *user);
void (*hook_destroy)(struct object_t*); // free resources
const char* (*hook_desc)(struct object_t*, user_t*); // get object description
@@ -65,8 +60,9 @@ struct obj_alias_t {
struct obj_alias_t *next;
};
-/* world modules should not instantiate this directly, use obj_new() instead */
-/* also, members marked with 'protected' should not be modified by the world module */
+/* world modules should not instantiate this directly, use obj_new()
+ * instead also, fields marked with 'protected' should not be modified
+ * by the world module */
struct object_t {
obj_id id; // protected
@@ -75,17 +71,17 @@ struct object_t {
* room */
char *name;
- struct obj_class_t *class;
+ struct obj_class_t *class; // protected
size_t n_alias;
- struct obj_alias_t *alias_list;
+ struct obj_alias_t *alias_list; // protected
- bool list; /* whether to list in room view */
+ bool hidden; /* whether to list in room description */
bool default_article; /* whether or not to use 'a' or 'an' when describing this */
void *userdata;
- unsigned refcount; // private
+ unsigned refcount; // protected
};
/* returns a new object of class 'c' */
@@ -100,10 +96,12 @@ struct object_t *obj_read(int fd);
/* this adds a reference to an object, DOES NOT COPY */
struct object_t *obj_dup(struct object_t *obj);
-/* makes a new object with a new ID, but same data fields as the original */
+/* makes a new object with a new ID, but with the same data fields as
+ * the original */
struct object_t *obj_copy(struct object_t *obj);
-/* this only frees the object if its reference count is zero */
+/* decrements an object's reference count; frees the object if there
+ * are no more references to it */
void obj_free(void*);
/* shut down the obj_* module */
diff --git a/src/room.c b/src/room.c
index 23ea5b7..9cc8c8c 100644
--- a/src/room.c
+++ b/src/room.c
@@ -80,9 +80,15 @@ void room_free(struct room_t *room)
bool room_obj_add(room_id room, struct object_t *obj)
{
+ debugf("ADDING OBJECT %s to ROOM %d\n", obj->name, room);
+
bool status = true;
if(!multimap_insert(room_get(room)->objects, obj->name, obj))
+ {
+ debugf("FAILED TO ADD OBJECT.\n");
status = false;
+ }
+
struct obj_alias_t *iter = obj->alias_list;
while(iter)
{
@@ -94,6 +100,9 @@ bool room_obj_add(room_id room, struct object_t *obj)
}
iter = iter->next;
}
+
+ debugf("ROOM %d now has %d objects\n", room, multimap_size(room_get(room)->objects));
+
return status;
}
@@ -116,16 +125,22 @@ bool room_obj_add_alias(room_id room, struct object_t *obj, char *alias)
iter = iter->next;
}
+ debugf("adding alias '%s' for object '%s'\n", alias, obj->name);
+
+ debugf("ROOM %d now has %d total object names\n", room, multimap_size(room_get(room)->objects));
+
struct obj_alias_t *new = calloc(1, sizeof(struct obj_alias_t));
- new->alias = alias;
+ new->alias = strdup(alias);
new->next = obj->alias_list;
obj->alias_list = new;
++obj->n_alias;
- return multimap_insert(room_get(room)->objects, alias, obj_dup(obj));
+ bool status = multimap_insert(room_get(room)->objects, alias, obj_dup(obj));
+
+ return status;
}
const struct multimap_list *room_obj_iterate(room_id room, void **save, size_t *n_pairs)
@@ -160,6 +175,7 @@ size_t room_obj_count_noalias(room_id id)
bool room_obj_del_by_ptr(room_id room, struct object_t *obj)
{
+ debugf("room_obj_del_by_ptr: deleting object %s\n", obj->name);
struct obj_alias_t *iter = obj->alias_list;
struct object_t tmp;
@@ -167,14 +183,17 @@ bool room_obj_del_by_ptr(room_id room, struct object_t *obj)
while(iter)
{
+ debugf(" deleting alias %s\n", iter->alias);
multimap_delete(room_get(room)->objects, iter->alias, &tmp);
iter = iter->next;
}
+ debugf("After deleting aliases of object: %s:\n", obj->name);
+
return multimap_delete(room_get(room)->objects, obj->name, &tmp);
}
-/* delete all the objects with a matching name, and all their aliases,
+/* delete all the objects with a matching name, and all their aliases
* from a room */
bool room_obj_del(room_id room, const char *name)
diff --git a/src/room.h b/src/room.h
index e02105c..e9e1953 100644
--- a/src/room.h
+++ b/src/room.h
@@ -28,9 +28,9 @@
are added by hooks in rooms, which are provided by the world
module. */
-typedef enum room_id { ROOM_NONE = -1 } room_id;
+typedef struct child_data user_t; // definition of child_data in server.h
-typedef struct child_data user_t;
+typedef enum room_id { ROOM_NONE = -1 } room_id;
enum direction_t { DIR_N = 0, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_UP, DIR_DN, DIR_IN, DIR_OT, NUM_DIRECTIONS };
@@ -46,8 +46,12 @@ struct roomdata_t {
const char * const adjacent[NUM_DIRECTIONS];
void (* const hook_init)(room_id id);
- void (* const hook_enter)(room_id room, user_t *user);
- void (* const hook_leave)(room_id room, user_t *user);
+
+ /* return values indicate permission to enter/leave,
+ * setting to NULL defaults to true.
+ */
+ bool (* const hook_enter)(room_id room, user_t *user);
+ bool (* const hook_leave)(room_id room, user_t *user);
void (* const hook_serialize)(room_id room, int fd);
void (* const hook_deserialize)(room_id room, int fd);
void (* const hook_destroy)(room_id room);
@@ -88,6 +92,7 @@ bool room_obj_add_alias(room_id room, struct object_t *obj, char *alias);
bool room_obj_del(room_id room, const char *name);
bool room_obj_del_alias(room_id room, struct object_t *obj, const char *alias);
+bool room_obj_del_by_ptr(room_id room, struct object_t *obj);
const struct multimap_list *room_obj_get(room_id room, const char *obj);
const struct multimap_list *room_obj_get_size(room_id room, const char *name, size_t *n_objs);
diff --git a/src/server.c b/src/server.c
index 9e2e465..e42483c 100644
--- a/src/server.c
+++ b/src/server.c
@@ -45,12 +45,15 @@ static int server_socket;
/* saves state periodically */
void server_save_state(bool force)
{
- static int n = 0;
- n = (n + 1) % SAVE_INTERVAL;
- if(!n || force)
+ if(!are_child)
{
- world_save(WORLDFILE);
- userdb_write(USERFILE);
+ static int n = 0;
+ n = (n + 1) % SAVE_INTERVAL;
+ if(!n || force)
+ {
+ world_save(WORLDFILE);
+ userdb_write(USERFILE);
+ }
}
}
@@ -119,6 +122,10 @@ static void __attribute__((noreturn)) server_cleanup(void)
close(server_socket);
+ /* save state */
+ if(!are_child)
+ server_save_state(true);
+
/* shut down modules */
client_shutdown();
obj_shutdown();
@@ -152,7 +159,7 @@ static void __attribute__((noreturn)) sigint_handler(int s)
}
static bool autoconfig = false;
-const char *autouser, *autopass;
+static const char *autouser, *autopass;
static void check_userfile(void)
{
diff --git a/src/server.h b/src/server.h
index af7e9fc..95e537a 100644
--- a/src/server.h
+++ b/src/server.h
@@ -26,21 +26,29 @@
#include "server_reqs.h"
#include "room.h"
+/* everything the server needs to manage its children */
struct child_data {
- pid_t pid;
- int readpipe[2];
- int outpipe[2];
+ pid_t pid;
- int state;
- room_id room;
- char *user;
+ /* pipes, packet mode */
+ int readpipe[2];
+ int outpipe[2];
- ev_io *io_watcher;
+ /* user state */
+ int state;
+ room_id room;
+ char *user;
+
+ /* libev watchers */
+ ev_io *io_watcher;
ev_child *sigchld_watcher;
+ /* remote IP */
struct in_addr addr;
};
+typedef struct child_data user_t;
+
extern volatile int num_clients;
extern void *child_map;
extern bool are_child;
diff --git a/src/server_reqs.c b/src/server_reqs.c
index 167331d..fffdee1 100644
--- a/src/server_reqs.c
+++ b/src/server_reqs.c
@@ -157,42 +157,53 @@ static void req_send_desc(unsigned char *data, size_t datalen, struct child_data
room_id id = sender->room;
while(1)
{
- debugf("Iterating over object name...\n");
size_t n_objs;
- const struct multimap_list *iter= room_obj_iterate(id, &save, &n_objs);
+ const struct multimap_list *iter = room_obj_iterate(id, &save, &n_objs);
id = ROOM_NONE;
if(!iter)
break;
const char *name = iter->key;
struct object_t *obj = iter->val;
- if(!strcmp(name, obj->name))
+
+ debugf("*** ITERATING OVER OBJECT IN ROOM ***\n");
+ debugf("hidden: %d\n", obj->hidden);
+ debugf("compare: %s %s\n", obj->name, name);
+
+ buf[0] = '\0';
+
+ if(!obj->hidden)
{
- if(n_objs == 1)
+ if(!strcmp(name, obj->name))
{
- char *article = (is_vowel(name[0])?"an":"a");
- strlcat(buf, "There is ", sizeof(buf));
- if(obj->default_article)
+ if(n_objs == 1)
{
- strlcat(buf, article, sizeof(buf));
- strlcat(buf, " ", sizeof(buf));
+ char *article = (is_vowel(name[0])?"an":"a");
+ strlcat(buf, "There is ", sizeof(buf));
+ if(obj->default_article)
+ {
+ strlcat(buf, article, sizeof(buf));
+ strlcat(buf, " ", sizeof(buf));
+ }
+ strlcat(buf, name, sizeof(buf));
+ strlcat(buf, " here.\n", sizeof(buf));
+ }
+ else
+ {
+ strlcat(buf, "There are ", sizeof(buf));
+ char n[32];
+ snprintf(n, sizeof(n), "%lu ", n_objs);
+ strlcat(buf, n, sizeof(buf));
+ strlcat(buf, name, sizeof(buf));
+ strlcat(buf, "s here.\n", sizeof(buf));
}
- strlcat(buf, name, sizeof(buf));
- strlcat(buf, " here.\n", sizeof(buf));
- }
- else
- {
- strlcat(buf, "There are ", sizeof(buf));
- char n[32];
- snprintf(n, sizeof(n), "%lu ", n_objs);
- strlcat(buf, n, sizeof(buf));
- strlcat(buf, name, sizeof(buf));
- strlcat(buf, "s here.\n", sizeof(buf));
}
+
+ send_msg(sender, "%s", buf);
}
+ else
+ debugf("OBJECT IS HIDDEN\n");
}
-
- send_packet(sender, REQ_BCASTMSG, buf, strlen(buf));
}
static void req_send_roomname(unsigned char *data, size_t datalen, struct child_data *sender)
@@ -333,7 +344,7 @@ static void req_look_at(unsigned char *data, size_t datalen, struct child_data *
if(inv_list)
{
send_msg(sender, "In inventory:\n");
- idx = print_objlist(sender, inv_list, idx, n_objs);
+ print_objlist(sender, inv_list, idx, n_objs);
}
if(!room_list && !inv_list)
@@ -355,10 +366,12 @@ static void req_take(unsigned char *data, size_t datalen, struct child_data *sen
if(obj->class->hook_take && !obj->class->hook_take(obj, sender))
{
send_msg(sender, "You can't take that.\n");
- return;
+ iter = next;
+ continue;
}
userdb_add_obj(sender->user, obj);
+ room_obj_del_by_ptr(sender->room, obj);
send_msg(sender, "Taken.\n");
}
@@ -367,8 +380,6 @@ static void req_take(unsigned char *data, size_t datalen, struct child_data *sen
iter = next;
}
- room_obj_del(sender->room, (const char*)data);
-
server_save_state(false);
}
else
@@ -452,17 +463,21 @@ static void req_drop(unsigned char *data, size_t datalen, struct child_data *sen
while(iter)
{
+ const struct multimap_list *next = iter->next;
struct object_t *obj = iter->val;
- struct object_t *dup = obj_dup(obj);
- room_obj_add(sender->room, dup);
+ if(!obj->class->hook_drop || (obj->class->hook_drop && obj->class->hook_drop(obj, sender)))
+ {
+ send_msg(sender, "Dropped.\n");
+ room_obj_add(sender->room, obj_dup(obj));
+ userdb_del_obj_by_ptr(sender->user, obj);
+ }
+ else
+ send_msg(sender, "You cannot drop that.\n");
- send_msg(sender, "Dropped.\n");
- iter = iter->next;
+ iter = next;
}
- multimap_delete_all(user->objects, (const char*)data);
-
server_save_state(false);
}
diff --git a/src/server_reqs.h b/src/server_reqs.h
index 5137f9d..c77c53a 100644
--- a/src/server_reqs.h
+++ b/src/server_reqs.h
@@ -16,6 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#pragma once
+
+#include "globals.h"
+
+typedef struct child_data user_t;
+
/* child<->master commands */
/* children might not implement all of these */
/* meanings might be different for the server and child, see comments */
diff --git a/src/userdb.c b/src/userdb.c
index dde2693..101b6d0 100644
--- a/src/userdb.c
+++ b/src/userdb.c
@@ -183,7 +183,6 @@ bool userdb_remove(const char *key)
bool userdb_add(struct userdata_t *data)
{
- userdb_dump();
struct userdata_t *new = calloc(1, sizeof(*new)); /* only in C! */
memcpy(new, data, sizeof(*new));
@@ -239,9 +238,6 @@ void userdb_dump(void)
void userdb_shutdown(void)
{
- if(map && db_file && !are_child)
- userdb_write(db_file);
-
if(map)
{
hash_free(map);
@@ -283,6 +279,39 @@ bool userdb_add_obj(const char *name, struct object_t *obj)
return multimap_insert(user->objects, obj->name, obj_dup(obj));
}
+bool userdb_del_obj_by_ptr(const char *username, struct object_t *obj)
+{
+ struct userdata_t *user = userdb_lookup(username);
+
+ struct obj_alias_t *iter = obj->alias_list;
+
+ struct object_t tmp;
+ tmp.id = obj->id;
+
+ while(iter)
+ {
+ multimap_delete(user->objects, iter->alias, &tmp);
+ iter = iter->next;
+ }
+
+ return multimap_delete(user->objects, obj->name, &tmp);
+}
+
+bool userdb_del_obj(const char *username, const char *obj_name)
+{
+ struct userdata_t *user = userdb_lookup(username);
+ const struct multimap_list *iter = multimap_lookup(user->objects, obj_name, NULL);
+ while(iter)
+ {
+ const struct multimap_list *next = iter->next;
+ struct object_t *obj = iter->val;
+ userdb_del_obj_by_ptr(username, obj);
+ iter = next;
+ }
+
+ return true;
+}
+
/*** child request wrappers ***/
/* NOTE: these also work from the master, but it's better to use the
* userdb_* funcs instead */
diff --git a/src/userdb.h b/src/userdb.h
index 52ade12..25bdc7b 100644
--- a/src/userdb.h
+++ b/src/userdb.h
@@ -66,7 +66,9 @@ bool userdb_write(const char*);
/* *save should be set to NULL on the first run */
struct userdata_t *userdb_iterate(void **save);
-bool userdb_add_obj(const char *name, struct object_t *obj);
+bool userdb_add_obj(const char *username, struct object_t *obj);
+bool userdb_del_obj(const char *username, const char *obj_name);
+bool userdb_del_obj_by_ptr(const char *username, struct object_t *obj);
/*** child-only functions ***/
struct userdata_t *userdb_request_lookup(const char *name);
diff --git a/src/verb.h b/src/verb.h
index cdfbe98..348da49 100644
--- a/src/verb.h
+++ b/src/verb.h
@@ -30,6 +30,9 @@
* callbacks.
*/
+struct child_data;
+typedef struct child_data user_t;
+
struct verb_t;
struct verb_class_t {
const char *class_name;
diff --git a/src/world.c b/src/world.c
index 1516b4c..a854e49 100644
--- a/src/world.c
+++ b/src/world.c
@@ -80,6 +80,8 @@ void world_save(const char *fname)
size_t n_objects = room_obj_count_noalias(i);
write(fd, &n_objects, sizeof(n_objects));
+ debugf("Room %d has %d objects.\n", i, n_objects);
+
room_id id = i;
void *save;
while(1)
@@ -95,7 +97,10 @@ void world_save(const char *fname)
break;
const char *name = iter->key;
if(!strcmp(name, obj->name))
- obj_write(fd, obj);
+ {
+ debugf("writing object '%s' in room %d\n", obj->name, i);
+ obj_write(fd, obj);
+ }
iter = iter->next;
}
}