btmux-0.6-rc4/doc/
btmux-0.6-rc4/event/
btmux-0.6-rc4/game/
btmux-0.6-rc4/game/maps/
btmux-0.6-rc4/game/mechs/
btmux-0.6-rc4/game/text/help/
btmux-0.6-rc4/game/text/help/cat_faction/
btmux-0.6-rc4/game/text/help/cat_inform/
btmux-0.6-rc4/game/text/help/cat_misc/
btmux-0.6-rc4/game/text/help/cat_mux/
btmux-0.6-rc4/game/text/help/cat_mux/cat_commands/
btmux-0.6-rc4/game/text/help/cat_mux/cat_functions/
btmux-0.6-rc4/game/text/help/cat_templates/
btmux-0.6-rc4/game/text/wizhelp/
btmux-0.6-rc4/include/
btmux-0.6-rc4/misc/
btmux-0.6-rc4/python/
btmux-0.6-rc4/src/hcode/btech/
btmux-0.6-rc4/tree/
/*
 * db_xdr.c
 */
#include "copyright.h"
#include "config.h"

#include "mudconf.h"
#include "config.h"
#include "externs.h"
#include "db.h"
#include "vattr.h"
#include "attrs.h"
#include "alloc.h"
#include "powers.h"
#include "mmdb.h"
#include "debug.h"

/* adds for commac */
#include "macro.h"
#include "commac.h"
#include "comsys.h"
#include "myfifo.h"
#include "create.h"

extern OBJ *db;

static void do_save_com_xdr(chmsg * d,struct mmdb_t *mmdb)
{
        mmdb_write_uint32(mmdb, (int) d->time);

        mmdb_write_opaque(mmdb, d->msg, strlen(d->msg)+1);

}

void myfifo_trav_r_xdr(myfifo ** foo, struct mmdb_t *mmdb, void (*func) ())
{
        myfifo_e *tmp;


        for (tmp = (*foo)->last; tmp !=NULL; tmp = tmp->prev)
                func(tmp->data, mmdb);
}

void mmdb_write_object(struct mmdb_t *mmdb, dbref object)
{
	ATRLIST *atrlist;

	mmdb_write_uint(mmdb, object);
	mmdb_write_opaque(mmdb, Name(object), strlen(Name(object)) + 1);
	mmdb_write_uint(mmdb, Location(object));
	mmdb_write_uint(mmdb, Zone(object));
	mmdb_write_uint(mmdb, Contents(object));
	mmdb_write_uint(mmdb, Exits(object));
	mmdb_write_uint(mmdb, Link(object));
	mmdb_write_uint(mmdb, Next(object));
	mmdb_write_uint(mmdb, Owner(object));
	mmdb_write_uint(mmdb, Parent(object));
	mmdb_write_uint(mmdb, Pennies(object));
	mmdb_write_uint(mmdb, Flags(object));
	mmdb_write_uint(mmdb, Flags2(object));
	mmdb_write_uint(mmdb, Flags3(object));
	mmdb_write_uint(mmdb, Powers(object));
	mmdb_write_uint(mmdb, Powers2(object));
	mmdb_write_uint(mmdb, db[object].at_count);
	atrlist = db[object].ahead;
	for(int i = 0; i < db[object].at_count; i++) {
		mmdb_write_opaque(mmdb, atrlist[i].data, atrlist[i].size);
		mmdb_write_uint(mmdb, atrlist[i].number);
	}
}

#define DB_MAGIC 0x4841475A
#define DB_VERSION 3
#define COMMAC_MAGIC   0x434f4d5a  /* COMZ */
#define COMMAC_VERSION 1

struct string_dict_entry {
        char *key;
        char *data;
};

static int mmdb_write_vattr(void *key, void *data, int depth, void *arg)
{
	struct mmdb_t *mmdb = (struct mmdb_t *) arg;
	struct string_dict_entry *ent = data;
	VATTR *vp = (VATTR *) ent->data;

	mmdb_write_opaque(mmdb, vp->name, strlen(vp->name) + 1);
	mmdb_write_uint(mmdb, vp->number);
	mmdb_write_uint(mmdb, vp->flags);
	return 1;
}

void mmdb_db_write(char *filename)
{
	struct mmdb_t *mmdb;
	uint32_t xid[5], i;
	struct timeval tv;
	rbtree vattr_htab = mudstate.vattr_name_htab.tree;
/* commac specific */
	int j, k, np, player_users;
	struct commac *c;
	struct channel *ch;
	struct comuser *user;
	struct macros *m;

	for(i = 0; i < 5; i++) {
		xid[i] = rand();
	}

	gettimeofday(&tv, NULL);

	mmdb = mmdb_open_write(filename);
	mmdb_write_uint(mmdb, DB_MAGIC);
	mmdb_write_uint(mmdb, DB_VERSION);
	mmdb_write_uint(mmdb, tv.tv_sec);
	mmdb_write_uint(mmdb, tv.tv_usec);
	mmdb_write_uint(mmdb, mudstate.db_revision++);
	for(i = 0; i < 5; i++) {
		mmdb_write_uint(mmdb, xid[i]);
	}
	mmdb_write_uint(mmdb, rb_size(vattr_htab));
	rb_walk(vattr_htab, WALK_INORDER, mmdb_write_vattr, mmdb);
	mmdb_write_uint(mmdb, mudstate.db_top);
	DO_WHOLE_DB(i) {
		mmdb_write_object(mmdb, i);
	}

	/* START COMMAC */
	mmdb_write_uint32(mmdb, COMMAC_MAGIC);
	mmdb_write_uint32(mmdb, COMMAC_VERSION);
	
	purge_commac();
	np = 0;
	
	for(i = 0; i < NUM_COMMAC; i++) {
		c = commac_table[i];
		while (c) {
			np++;
			c = c->next;
		}
	}

	mmdb_write_uint32(mmdb, np);

	for(i = 0; i < NUM_COMMAC; i++) {
		c = commac_table[i];
		while (c) {
			mmdb_write_uint32(mmdb, c->who);
			mmdb_write_uint32(mmdb, c->numchannels);
			mmdb_write_uint32(mmdb, c->macros[0]);
			mmdb_write_uint32(mmdb, c->macros[1]);
			mmdb_write_uint32(mmdb, c->macros[2]);
			mmdb_write_uint32(mmdb, c->macros[3]);
			mmdb_write_uint32(mmdb, c->macros[4]);
			mmdb_write_uint32(mmdb, c->curmac);
			if(c->numchannels > 0) {
				for(j = 0; j <c->numchannels; j++) {
					mmdb_write_opaque(mmdb, c->alias +j *6, strlen(c->alias +j * 6)+1);
					mmdb_write_opaque(mmdb, c->channels[j], strlen(c->channels[j])+1);
				}
			}
			c = c->next;
		}
	}
	/* END COMMAC */
	/* START COMSYS */
	mmdb_write_uint32(mmdb, num_channels);
	for(ch = (struct channel *) hash_firstentry(&mudstate.channel_htab); ch; ch = (struct channel *) hash_nextentry(&mudstate.channel_htab)) {
		mmdb_write_opaque(mmdb, ch->name, strlen(ch->name)+1);
		mmdb_write_uint32(mmdb, ch->type);
		mmdb_write_uint32(mmdb, ch->charge);
		mmdb_write_uint32(mmdb, ch->charge_who);
		mmdb_write_uint32(mmdb, ch->amount_col);
		mmdb_write_uint32(mmdb, ch->num_messages);
		mmdb_write_uint32(mmdb, ch->chan_obj);
		k = myfifo_length(&ch->last_messages);
		mmdb_write_uint32(mmdb, k);

		if (k)
			myfifo_trav_r_xdr(&ch->last_messages,mmdb,do_save_com_xdr);

		player_users = 0;
		for(j = 0; j < ch->num_users; j++) 
			if(isPlayer(ch->users[j]->who) || isRobot(ch->users[j]->who))
				player_users++;

		mmdb_write_uint32(mmdb,player_users);
		for(j = 0; j < ch->num_users; j++) {
			user = ch->users[j];
			if(!isPlayer(user->who) && !isRobot(user->who))
				continue;
			mmdb_write_uint32(mmdb, user->who);
			mmdb_write_uint32(mmdb, user->on);
			if(strlen(user->title)) {
				mmdb_write_uint32(mmdb,1);
				mmdb_write_opaque(mmdb,user->title,strlen(user->title)+1);
			} else
				mmdb_write_uint32(mmdb,0);
		}
	}

	/* END COMSYS */
	/* START MACRO */
	mmdb_write_uint32(mmdb, nummacros);

        for(i = 0; i <nummacros; i++) {
                m = macros[i];
                mmdb_write_uint32(mmdb, m->player);
                mmdb_write_uint32(mmdb, m->nummacros);
                mmdb_write_uint32(mmdb, (int) m->status);
                mmdb_write_opaque(mmdb, m->desc, strlen(m->desc)+1);
                for(j = 0; j < m->nummacros; j++) {
                        mmdb_write_opaque(mmdb, m->alias + j * 5, strlen(m->alias +j * 5)+1);
                        mmdb_write_opaque(mmdb, m->string[j], strlen(m->string[j])+1);
                }
        }
	/* END MACRO */
	mmdb_close(mmdb);
}

int mmdb_db_read(char *filename)
{
	struct mmdb_t *mmdb;
	uint32_t xid[5], i;
	uint32_t magic, version, revision;
	uint32_t object;
	uint32_t vattr_count, object_count;
	uint32_t vattr_len, vattr_number, vattr_flags;
	struct timeval tv;
	rbtree vattr_htab = mudstate.vattr_name_htab.tree;
	char buffer[4096];
	int np, j, k, len;
	struct commac *c;
	struct channel *ch;
	struct comuser *user;
	struct macros *m;

	mmdb = mmdb_open_read(filename);
	magic = mmdb_read_uint32(mmdb);
	dassert(magic == DB_MAGIC);
	version = mmdb_read_uint32(mmdb);
	dassert(version == DB_VERSION);

	tv.tv_sec = mmdb_read_uint32(mmdb);
	tv.tv_usec = mmdb_read_uint32(mmdb);

	mudstate.db_revision = revision = mmdb_read_uint32(mmdb);

	dprintk("Loading database revision %d, created at %s.", revision,
			asctime(localtime(&tv.tv_sec)));
	for(i = 0; i < 5; i++) {
		xid[i] = mmdb_read_uint32(mmdb);
	}

	dprintk("database XID: %08x%08x%08x%08x%08x", xid[0],
			xid[1], xid[2], xid[3], xid[4]);
	db_free();
	vattr_count = mmdb_read_uint32(mmdb);
	anum_extend(vattr_count);
	dprintk("reading in %d vattrs", vattr_count);
	for(int i = 0; i < vattr_count; i++) {
		vattr_len = mmdb_read_uint32(mmdb);
		mmdb_read(mmdb, buffer, vattr_len);
		vattr_number = mmdb_read_uint32(mmdb);
		vattr_flags = mmdb_read_uint32(mmdb);
		vattr_define(buffer, vattr_number, vattr_flags);
	}
	dprintk("... done.");

	object_count = mmdb_read_uint32(mmdb);
	db_grow(object_count);
	dprintk("reading in %d objects", object_count);
	for(int i = 0; i < object_count; i++) {
		object = mmdb_read_uint32(mmdb);
		vattr_len = mmdb_read_uint32(mmdb);
		mmdb_read(mmdb, buffer, vattr_len);
		s_Name(object, buffer);
		s_Location(object, mmdb_read_uint32(mmdb));
		s_Zone(object, mmdb_read_uint32(mmdb));
		s_Contents(object, mmdb_read_uint32(mmdb));
		s_Exits(object, mmdb_read_uint32(mmdb));
		s_Link(object, mmdb_read_uint32(mmdb));
		s_Next(object, mmdb_read_uint32(mmdb));
		s_Owner(object, mmdb_read_uint32(mmdb));
		s_Parent(object, mmdb_read_uint32(mmdb));
		s_Pennies(object, mmdb_read_uint32(mmdb));
		s_Flags(object, mmdb_read_uint32(mmdb));
		s_Flags2(object, mmdb_read_uint32(mmdb));
		s_Flags3(object, mmdb_read_uint32(mmdb));
		s_Powers(object, mmdb_read_uint32(mmdb));
		s_Powers2(object, mmdb_read_uint32(mmdb));
		vattr_count = mmdb_read_uint32(mmdb);
		for(int j = 0; j < vattr_count; j++) {
			vattr_len = mmdb_read_uint32(mmdb);
			mmdb_read(mmdb, buffer, vattr_len);
			vattr_number = mmdb_read_uint32(mmdb);
			atr_add_raw(object, vattr_number, buffer);
		}
	}
	load_player_names();
	
	magic = mmdb_read_uint32(mmdb);
	dassert(magic == COMMAC_MAGIC);
	version = mmdb_read_uint32(mmdb);
	dassert(version == COMMAC_VERSION);
        /* START COMMAC SECTION */
	np = mmdb_read_uint32(mmdb);
	for(i = 0; i < np; i++) {
		c = create_new_commac();
		c->who = mmdb_read_uint32(mmdb);
		c->numchannels = mmdb_read_uint32(mmdb);
		c->macros[0] = mmdb_read_uint32(mmdb);
		c->macros[1] = mmdb_read_uint32(mmdb);
		c->macros[2] = mmdb_read_uint32(mmdb);
		c->macros[3] = mmdb_read_uint32(mmdb);
		c->macros[4] = mmdb_read_uint32(mmdb);
		c->curmac = mmdb_read_uint32(mmdb);
		c->maxchannels = c->numchannels;
		if(c->maxchannels > 0) {
			c->alias = (char *) malloc(c->maxchannels * 6);
			c->channels = (char **) malloc(sizeof(char *) * c->maxchannels);
			
			for(j = 0; j < c->numchannels; j++) {
				len = mmdb_read_uint32(mmdb);
				mmdb_read(mmdb, buffer, len);

				StringCopy(c->alias + j * 6,buffer);

				len = mmdb_read_uint32(mmdb);
				mmdb_read(mmdb, buffer, len);
	
				c->channels[j] = (char *) malloc(strlen(buffer) + 1);
				StringCopy(c->channels[j],buffer);

			}
			sort_com_aliases(c);
		} else {
			c->alias = NULL;
			c->channels = NULL;
		}
		if((Typeof(c->who) == TYPE_PLAYER) || (!God(Owner(c->who))) || ((!Going(c->who))))
			add_commac(c);
		purge_commac();
	}
	/* END COMMAC SECTION */

	/* START COMSYS SECTION */
	num_channels = mmdb_read_uint32(mmdb);

	for( i = 0; i < num_channels; i++) {
		ch = (struct channel *) malloc(sizeof(struct channel));
		
	
		len = mmdb_read_uint32(mmdb);
		mmdb_read(mmdb,buffer,len);

		strncpy(ch->name, buffer, len);
		ch->on_users = NULL;
		
		hashadd(ch->name, (int *) ch, &mudstate.channel_htab);
		ch->type = mmdb_read_uint32(mmdb);
		ch->charge = mmdb_read_uint32(mmdb);
		ch->charge_who = mmdb_read_uint32(mmdb);
		ch->amount_col = mmdb_read_uint32(mmdb);
		ch->num_messages = mmdb_read_uint32(mmdb);
		ch->chan_obj = mmdb_read_uint32(mmdb);
		k = mmdb_read_uint32(mmdb);
		ch->last_messages = NULL;
		
		if (k > 0) {
			for(j = 0; j < k; j++) {
				chmsg *c;
				Create(c,chmsg,1);
				c->time = mmdb_read_uint32(mmdb);
				len = mmdb_read_uint32(mmdb);
				mmdb_read(mmdb, buffer, len);
				c->msg = strdup(buffer);
				myfifo_push(&ch->last_messages, c);
			}
			
		}
		ch->num_users = mmdb_read_uint32(mmdb);
		ch->max_users = ch->num_users;

		if(ch->num_users > 0) {
			ch->users = (struct comuser **) calloc(ch->max_users, sizeof(struct comuser *));
			
			for(j =0; j < ch->num_users; j++) {
				user = (struct comuser *) malloc(sizeof(struct comuser));

				ch->users[j] = user;

				user->who = mmdb_read_uint32(mmdb);
				user->on = mmdb_read_uint32(mmdb);

				/* title stuff here */
				k = mmdb_read_uint32(mmdb);
				if (k) {
					len = mmdb_read_uint32(mmdb);
					mmdb_read(mmdb, buffer, len);
					user->title = strdup(buffer);
				}
				else
					user->title = "";
				if(!(isPlayer(user->who)) && !(Going(user->who) && (God(Owner(user->who))))) {
					do_joinchannel(user->who, ch);
					user->on_next = ch->on_users;
					ch->on_users = user;
				} else {
					user->on_next = ch->on_users;
					ch->on_users = user;
				}
			}
			sort_users(ch);
		} else
			ch->users = NULL;
	}		


	/* END COMSYS SECTION */

	/* BEGIN MACRO SECTION */
	nummacros = mmdb_read_uint32(mmdb);
	maxmacros = nummacros;
	
	if(maxmacros > 0)
		macros = (struct macros **) malloc(sizeof(struct macros *) * nummacros);
	else
		macros = NULL;

	for(i = 0; i < nummacros; i++) {
		macros[i] = (struct macros *) malloc(sizeof(struct macros));

		m = macros[i];
		m->player = mmdb_read_uint32(mmdb);
		m->nummacros = mmdb_read_uint32(mmdb);
		m->status = mmdb_read_uint32(mmdb);
		len = mmdb_read_uint32(mmdb);
		mmdb_read(mmdb, buffer, len);
		m->desc = strdup(buffer);

		m->maxmacros = m->nummacros;

		if(m->nummacros > 0) {
			m->alias = (char *) malloc(5 * m->maxmacros);
			m->string = (char **) malloc(sizeof(char *) * m->nummacros);

			for(j = 0; j < m->nummacros; j++) {
				len = mmdb_read_uint32(mmdb);
				mmdb_read(mmdb, buffer, len);
				strcpy(m->alias + j * 5, buffer);
				len = mmdb_read_uint32(mmdb);
				mmdb_read(mmdb, buffer, len);
				m->string[j] = (char *) malloc(len + 1);
				strcpy(m->string[j], buffer);

			}
			do_sort_macro_set(m);
		} else {
			m->alias = NULL;
			m->string = NULL;
		}
	}
	while (1) {
		for(i = 0; i < nummacros; i++)
			if(!isPlayer(macros[i]->player))
				break;
		if( i >= nummacros)
			break;
		clear_macro_set(i);
	}
	return object_count;
}