fbmuck-6.01/contrib/jresolver/
fbmuck-6.01/contrib/jresolver/org/
fbmuck-6.01/contrib/jresolver/org/fuzzball/
fbmuck-6.01/docs/devel/
fbmuck-6.01/game/
fbmuck-6.01/game/logs/
fbmuck-6.01/game/muf/
fbmuck-6.01/scripts/
fbmuck-6.01/src_docs/
/* $Header: /cvsroot/fbmuck/fbmuck/src/player.c,v 1.9 2002/09/09 02:09:54 arcticwolf Exp $ */


#include "copyright.h"
#include "config.h"

#include "db.h"
#include "params.h"
#include "tune.h"
#include "interface.h"
#include "externs.h"

static hash_tab player_list[PLAYER_HASH_SIZE];

dbref
lookup_player(const char *name)
{
	hash_data *hd;

	if ((hd = find_hash(name, player_list, PLAYER_HASH_SIZE)) == NULL) {
		return NOTHING;
	} else {
		return (hd->dbval);
	}
}


int
check_password(dbref player, const char* password)
{
	char md5buf[64];
	const char *processed = password;
	const char *pword = PLAYER_PASSWORD(player);

	if (password == NULL) {
		MD5base64(md5buf, "", 0);
		processed = md5buf;
	} else {
		if (*password) {
			MD5base64(md5buf, password, strlen(password));
			processed = md5buf;
		}
	}

	if (!pword || !*pword)
		return 1;

	if (!strcmp(pword, processed))
		return 1;

	return 0;
}


void
set_password_raw(dbref player, const char* password)
{
	PLAYER_SET_PASSWORD(player, password);
	DBDIRTY(player);
}


void
set_password(dbref player, const char* password)
{
	char md5buf[64];
	const char *processed = password;

	if (*password) {
		MD5base64(md5buf, password, strlen(password));
		processed = md5buf;
	}
	
	if (PLAYER_PASSWORD(player))
		free((void *) PLAYER_PASSWORD(player));

	set_password_raw(player, alloc_string(processed));
}


dbref
connect_player(const char *name, const char *password)
{
	dbref player;

	if (*name == NUMBER_TOKEN && number(name + 1) && atoi(name + 1)) {
		player = (dbref) atoi(name + 1);
		if ((player < 0) || (player >= db_top) || (Typeof(player) != TYPE_PLAYER))
			player = NOTHING;
	} else {
		player = lookup_player(name);
	}
	if (player == NOTHING)
		return NOTHING;
	if (!check_password(player, password))
		return NOTHING;

	return player;
}

dbref
create_player(const char *name, const char *password)
{
	dbref player;

	if (!ok_player_name(name) || !ok_password(password))
		return NOTHING;

	/* else he doesn't already exist, create him */
	player = new_object();

	/* initialize everything */
	NAME(player) = alloc_string(name);
	DBFETCH(player)->location = tp_player_start;	/* home */
	FLAGS(player) = TYPE_PLAYER;
	OWNER(player) = player;
	ALLOC_PLAYER_SP(player);
	PLAYER_SET_HOME(player, tp_player_start);
	DBFETCH(player)->exits = NOTHING;

	PLAYER_SET_PENNIES(player, tp_start_pennies);
	set_password_raw(player, NULL);
	set_password(player, password);
	PLAYER_SET_CURR_PROG(player, NOTHING);
	PLAYER_SET_INSERT_MODE(player, 0);
	PLAYER_SET_IGNORE_CACHE(player, NULL);
	PLAYER_SET_IGNORE_COUNT(player, 0);
	PLAYER_SET_IGNORE_LAST(player, NOTHING);

	/* link him to tp_player_start */
	PUSH(player, DBFETCH(tp_player_start)->contents);
	add_player(player);
	DBDIRTY(player);
	DBDIRTY(tp_player_start);

	set_flags_from_tunestr(player, tp_pcreate_flags);

	return player;
}

void
do_password(dbref player, const char *old, const char *newobj)
{
	if (!PLAYER_PASSWORD(player) || !check_password(player, old)) {
		notify(player, "Sorry, old password did not match current password.");
	} else if (!ok_password(newobj)) {
		notify(player, "Bad new password (no spaces allowed).");
	} else {
		set_password(player, newobj);
		DBDIRTY(player);
		notify(player, "Password changed.");
	}
}

void
clear_players(void)
{
	kill_hash(player_list, PLAYER_HASH_SIZE, 0);
	return;
}

void
add_player(dbref who)
{
	hash_data hd;

	hd.dbval = who;
	if (add_hash(NAME(who), hd, player_list, PLAYER_HASH_SIZE) == NULL) {
		panic("Out of memory");
	} else {
		return;
	}
}


void
delete_player(dbref who)
{
	int result;
	char buf[BUFFER_LEN];
	char namebuf[BUFFER_LEN];
	int i, j;
	dbref found, ren;


	result = free_hash(NAME(who), player_list, PLAYER_HASH_SIZE);

	if (result) {
		wall_wizards
				("## WARNING: Playername hashtable is inconsistent.  Rebuilding it.  Don't panic.");
		clear_players();
		for (i = 0; i < db_top; i++) {
			if (Typeof(i) == TYPE_PLAYER) {
				found = lookup_player(NAME(i));
				if (found != NOTHING) {
					ren = (i == who) ? found : i;
					j = 0;
					do {
						snprintf(namebuf, sizeof(namebuf), "%s%d", NAME(ren), ++j);
					} while (lookup_player(namebuf) != NOTHING);

					snprintf(buf, sizeof(buf),
							"## Renaming %s(#%d) to %s to prevent name collision.",
							NAME(ren), ren, namebuf);
					wall_wizards(buf);

					log_status("SANITY NAME CHANGE: %s(#%d) to %s\n", NAME(ren), ren, namebuf);

					if (ren == found) {
						free_hash(NAME(ren), player_list, PLAYER_HASH_SIZE);
					}
					if (NAME(ren)) {
						free((void *) NAME(ren));
					}
					ts_modifyobject(ren);
					NAME(ren) = alloc_string(namebuf);
					add_player(ren);
				} else {
					add_player(i);
				}
			}
		}
		result = free_hash(NAME(who), player_list, PLAYER_HASH_SIZE);
		if (result) {
			wall_wizards
					("## WARNING: Playername hashtable still inconsistent.  Now you can panic.");
		}
	}

	return;
}