eldhamud/boards/
eldhamud/clans/
eldhamud/classes/
eldhamud/councils/
eldhamud/deity/
eldhamud/doc/
eldhamud/doc/DIKU/
eldhamud/doc/MERC/
eldhamud/doc/mudprogs/
eldhamud/houses/
/* IMC2 Freedom Client - Developed by Mud Domain.
 *
 * Copyright (C)2004 by Roger Libiez ( Samson )
 * Contributions by Johnathan Walker ( Xorith ), Copyright (C)2004
 * Additional contributions by Jesse Defer ( Garil ), Copyright (C)2004
 * Additional contributions by Rogel, Copyright (c) 2004
 * Comments and suggestions welcome: imc@imc2.org
 * License terms are available in the imc2freedom.license file.
 */

#ifndef __IMC2_H__
#define __IMC2_H__

/* The all important version ID string, which is hardcoded for now out of laziness.
 * This name was chosen to represent the ideals of not only the code, but of the
 * network which spawned it.
 */
#define IMC_VERSION_STRING "IMC2 Freedom CL-1c "
#define IMC_VERSION 2

/* Number of entries to keep in the channel histories */
#define MAX_IMCHISTORY 20
#define MAX_IMCTELLHISTORY 20

/* Remcon: Ask and ye shall receive. */
#define IMC_DIR          "../imc/"

#define IMC_CHANNEL_FILE IMC_DIR "imc.channels"
#define IMC_CONFIG_FILE  IMC_DIR "imc.config"
#define IMC_BAN_FILE     IMC_DIR "imc.ignores"
#define IMC_UCACHE_FILE  IMC_DIR "imc.ucache"
#define IMC_COLOR_FILE   IMC_DIR "imc.color"
#define IMC_HELP_FILE    IMC_DIR "imc.help"
#define IMC_CMD_FILE     IMC_DIR "imc.commands"
#define IMC_HOTBOOT_FILE IMC_DIR "imc.hotboot"

/* Make sure you set the macros in the imccfg.h file properly or things get ugly from here. */
#include "imccfg.h"

#define IMC_BUFF_SIZE 16384

/* Connection states stuff */
enum imc_constates
{
   IMC_OFFLINE, IMC_AUTH1, IMC_AUTH2, IMC_ONLINE
};

typedef enum
{
   IMCPERM_NOTSET, IMCPERM_NONE, IMCPERM_MORT, IMCPERM_IMM, IMCPERM_ADMIN, IMCPERM_IMP
} imc_permissions;

/* Flag macros */
#define IMCIS_SET(var, bit)         ((var) & (bit))
#define IMCSET_BIT(var, bit)        ((var) |= (bit))
#define IMCREMOVE_BIT(var, bit)     ((var) &= ~(bit))

/* Channel flags, only one so far, but you never know when more might be useful */
#define IMCCHAN_LOG      (1 <<  0)

/* Player flags */
#define IMC_TELL         (1 <<  0)
#define IMC_DENYTELL     (1 <<  1)
#define IMC_BEEP         (1 <<  2)
#define IMC_DENYBEEP     (1 <<  3)
#define IMC_INVIS        (1 <<  4)
#define IMC_PRIVACY      (1 <<  5)
#define IMC_DENYFINGER   (1 <<  6)
#define IMC_AFK          (1 <<  7)
#define IMC_COLORFLAG    (1 <<  8)
#define IMC_PERMOVERRIDE (1 <<  9)
#define IMC_NOTIFY       (1 << 10)

#define IMCPERM(ch)           (CH_IMCDATA((ch))->imcperm)
#define IMCFLAG(ch)           (CH_IMCDATA((ch))->imcflag)
#define FIRST_IMCIGNORE(ch)   (CH_IMCDATA((ch))->imcfirst_ignore)
#define LAST_IMCIGNORE(ch)    (CH_IMCDATA((ch))->imclast_ignore)
#define IMC_LISTEN(ch)        (CH_IMCDATA((ch))->imc_listen)
#define IMC_DENY(ch)          (CH_IMCDATA((ch))->imc_denied)
#define IMC_RREPLY(ch)        (CH_IMCDATA((ch))->rreply)
#define IMC_RREPLY_NAME(ch)   (CH_IMCDATA((ch))->rreply_name)
#define IMC_EMAIL(ch)         (CH_IMCDATA((ch))->email)
#define IMC_HOMEPAGE(ch)      (CH_IMCDATA((ch))->homepage)
#define IMC_AIM(ch)           (CH_IMCDATA((ch))->aim)
#define IMC_ICQ(ch)           (CH_IMCDATA((ch))->icq)
#define IMC_YAHOO(ch)         (CH_IMCDATA((ch))->yahoo)
#define IMC_MSN(ch)           (CH_IMCDATA((ch))->msn)
#define IMC_COMMENT(ch)       (CH_IMCDATA((ch))->comment)
#define IMCTELLHISTORY(ch,x)  (CH_IMCDATA((ch))->imc_tellhistory[(x)])
#define IMCISINVIS(ch)        ( IMCIS_SET( IMCFLAG((ch)), IMC_INVIS ) )
#define IMCAFK(ch)            ( IMCIS_SET( IMCFLAG((ch)), IMC_AFK ) )

/* Should not need to edit anything below this point */

#define LGST 4096 /* Large String */
#define SMST 1024 /* Small String */

/* Macro taken from DOTD codebase. Fcloses a file, then nulls its pointer for safety. */
#define IMCFCLOSE(fp)  fclose((fp)); (fp)=NULL;

/*
 * Memory allocation macros.
 */
#define IMCCREATE(result, type, number)                           \
do                                                                \
{                                                                 \
    if (!((result) = (type *) calloc ((number), sizeof(type))))   \
    {                                                             \
	imclog( "Malloc failure @ %s:%d\n", __FILE__, __LINE__ );   \
	abort();                                                    \
    }                                                             \
} while(0)

#define IMCRECREATE(result, type, number)                               \
do                                                                      \
{                                                                       \
   if(!((result) = (type *)realloc((result), sizeof(type) * (number)))) \
   {                                                                    \
      imclog( "Realloc failure @ %s:%d\n", __FILE__, __LINE__ );        \
      abort();                                                          \
   }                                                                    \
} while(0)

#define IMCDISPOSE(point)     \
do                            \
{                             \
   if((point))                \
   {                          \
      free((point));          \
      (point) = NULL;         \
   }                          \
} while(0)

#define IMCSTRALLOC strdup
#define IMCSTRFREE IMCDISPOSE

/* double-linked list handling macros -Thoric ( From the Smaug codebase ) */
/* Updated by Scion 8/6/1999 */
#define IMCLINK(link, first, last, next, prev)  \
do                                              \
{                                               \
   if ( !(first) )                              \
   {                                            \
      (first) = (link);                         \
      (last) = (link);                          \
   }                                            \
   else                                         \
      (last)->next = (link);                    \
   (link)->next = NULL;                         \
   if ((first) == (link))                       \
      (link)->prev = NULL;                      \
   else                                         \
      (link)->prev = (last);                    \
   (last) = (link);                             \
} while(0)

#define IMCINSERT(link, insert, first, next, prev)    \
do                                                    \
{                                                     \
   (link)->prev = (insert)->prev;                     \
   if ( !(insert)->prev )                             \
      (first) = (link);                               \
   else                                               \
      (insert)->prev->next = (link);                  \
   (insert)->prev = (link);                           \
   (link)->next = (insert);                           \
} while(0)

#define IMCUNLINK(link, first, last, next, prev) \
do                                               \
{                                                \
   if ( !(link)->prev )                          \
   {                                             \
      (first) = (link)->next;                    \
	if((first))                                \
	   (first)->prev = NULL;                   \
   }                                             \
   else                                          \
   {                                             \
      (link)->prev->next = (link)->next;         \
   }                                             \
   if( !(link)->next )                           \
   {                                             \
      (last) = (link)->prev;                     \
	if((last))                                 \
	   (last)->next = NULL;                    \
   }                                             \
   else                                          \
   {                                             \
      (link)->next->prev = (link)->prev;         \
   }                                             \
} while(0)

/* No real functional difference in alot of this, but double linked lists DO seem to handle better,
 * and they look alot neater too. Yes, readability IS important! - Samson
 */
typedef struct imc_channel IMC_CHANNEL;        /* Channels, both local and non-local */
typedef struct imc_packet IMC_PACKET;          /* It's a packet! */
typedef struct imc_packet_data IMC_PDATA;      /* Extra data fields for packets */
typedef struct imc_siteinfo SITEINFO;          /* The given mud :) */
typedef struct imc_remoteinfo REMOTEINFO;      /* Information on a mud connected to IMC */
typedef struct imc_ban_data IMC_BAN;           /* Mud level bans */
typedef struct imcchar_data IMC_CHARDATA;      /* Player flags */
typedef struct imc_ignore IMC_IGNORE;	     /* Player level ignores */
typedef struct imcucache_data IMCUCACHE_DATA;  /* User cache data for gender targetting socials */
typedef struct imc_color_table IMC_COLOR;      /* The Color config */
typedef struct imc_command_table IMC_CMD_DATA; /* Command table */
typedef struct imc_help_table IMC_HELP_DATA;   /* Help table */
typedef struct imc_cmd_alias IMC_ALIAS;        /* Big, bad, bloated command alias thing */
typedef struct imc_packet_handler IMC_PHANDLER; /* custom packet handlers added dynamically */

typedef void IMC_FUN( CHAR_DATA *ch, char *argument );
#define IMC_CMD( name ) void (name)( CHAR_DATA *ch, char *argument )

typedef void PACKET_FUN( IMC_PACKET *q, char *packet );
#define PFUN( name ) void (name)( IMC_PACKET *q, char *packet )

extern REMOTEINFO *first_rinfo;
extern REMOTEINFO *last_rinfo;
extern SITEINFO *this_imcmud;

/* Oh yeah, baby, that raunchy looking Merc structure just got the facelift of the century.
 * Thanks to Thoric and friends for the slick idea.
 */
struct imc_cmd_alias
{
   IMC_ALIAS *next;
   IMC_ALIAS *prev;
   char *name;
};

struct imc_command_table
{
   IMC_CMD_DATA *next;
   IMC_CMD_DATA *prev;
   IMC_ALIAS *first_alias;
   IMC_ALIAS *last_alias;
   IMC_FUN *function;
   char *name;
   int level;
   bool connected;
};

struct imc_help_table
{
   IMC_HELP_DATA *next;
   IMC_HELP_DATA *prev;
   char *name;
   char *text;
   int level;
};

struct imc_color_table
{
   IMC_COLOR *next;
   IMC_COLOR *prev;
   char *name;      /* the name of the color */
   char *mudtag;    /* What the mud uses for the raw tag */
   char *imctag;    /* The imc tilde code that represents the mudtag to the network */
};

struct imc_ignore
{
   IMC_IGNORE *next;
   IMC_IGNORE *prev;
   char *name;
};

struct imcucache_data
{
   IMCUCACHE_DATA *next;
   IMCUCACHE_DATA *prev;
   char *name;
   time_t time;
   int gender;
};

struct imcchar_data
{
   IMC_IGNORE *imcfirst_ignore; /* List of ignored people */
   IMC_IGNORE *imclast_ignore;
   char *rreply;      /* IMC reply-to */
   char *rreply_name; /* IMC reply-to shown to char */
   char *imc_listen;  /* Channels the player is listening to */
   char *imc_denied;  /* Channels the player has been denied use of */
   char *imc_tellhistory[MAX_IMCTELLHISTORY]; /* History of received imctells - Samson 1-21-04 */
   char *email;       /* Person's email address - for imcfinger - Samson 3-21-04 */
   char *homepage;    /* Person's homepage - Samson 3-21-04 */
   char *aim;         /* Person's AOL Instant Messenger screenname - Samson 3-21-04 */
   char *yahoo;       /* Person's Y! screenname - Samson 3-21-04 */
   char *msn;         /* Person's MSN Messenger screenname - Samson 3-21-04 */
   char *comment;     /* Person's personal comment - Samson 3-21-04 */
   long imcflag;      /* Flags set on the player */
   int icq;           /* Person's ICQ UIN Number - Samson 3-21-04 */
   int imcperm;       /* Permission level for the player */
};

struct imc_channel
{
   IMC_CHANNEL *next;
   IMC_CHANNEL *prev;
   char *name;         /* name of channel */
   char *owner;        /* owner (singular) of channel */
   char *operators;    /* current operators of channel */
   char *invited;
   char *excluded;
   char *local_name;   /* Operational localname */
   char *regformat;
   char *emoteformat;
   char *socformat;
   char *history[MAX_IMCHISTORY];
   long flags;
   short level;
   bool open;
   bool refreshed;
};

struct imc_packet_data
{
   IMC_PDATA *next;
   IMC_PDATA *prev;
   char field[IMC_BUFF_SIZE];
};

struct imc_packet
{
   IMC_PDATA *first_data;
   IMC_PDATA *last_data;
   char from[SMST];
   char to[SMST];
   char type[SMST];
   char route[SMST]; /* This is only used internally and not sent */
};

/* The mud's connection data for the router */
struct imc_siteinfo
{
   char *routername;    /* name of router */
   char *rhost;         /* DNS/IP of router */
   char *network;       /* Network name of the router, set at keepalive - Samson */
   char *serverpw;      /* server password */
   char *clientpw;      /* client password */
   char *localname;     /* One word localname */
   char *fullname;      /* FULL name of mud */
   char *ihost;         /* host AND port of mud */
   char *email;         /* contact address (email) */
   char *www;           /* homepage */
   char *base;          /* The mud's codebase name */
   char *details;       /* BRIEF description of mud */
   int iport;           /* The port the mud itself is on */
   int minlevel;        /* Minimum player level */
   int immlevel;        /* Immortal level */
   int adminlevel;      /* Admin level */
   int implevel;        /* Implementor level */
   unsigned short rport; /* remote port of router */
   bool md5;            /* Client will support MD5 authentication */
   bool md5pass;        /* Client is using MD5 authentication */
   bool autoconnect;    /* Do we autoconnect on bootup or not? - Samson */

   /* Conection parameters - These don't save in the config file */
   char inbuf[IMC_BUFF_SIZE];   /* input buffer */
   char incomm[IMC_BUFF_SIZE];
   char *outbuf;		/* output buffer */
   char *versionid;     /* Transient version id for the imclist */
   unsigned long outsize;
   int outtop;
   int desc;            /* descriptor */
   unsigned short state; /* connection state */
};

struct imc_remoteinfo
{
   REMOTEINFO *next;
   REMOTEINFO *prev;
   char *name;
   char *version;
   char *network;
   char *path;
   char *url;
   bool expired;
};

/* A mudwide ban */
struct imc_ban_data
{
   IMC_BAN *next;
   IMC_BAN *prev;
   char *name;
};

struct imc_packet_handler
{
   IMC_PHANDLER *next;
   IMC_PHANDLER *prev;
   PACKET_FUN *func;
   char *name;
};

bool imc_command_hook( CHAR_DATA *ch, char *command, char *argument );
void imc_hotboot( void );
void imc_startup( bool force, int desc, bool connected );
void imc_shutdown( bool reconnect );
void imc_initchar( CHAR_DATA *ch );
bool imc_loadchar( CHAR_DATA *ch, FILE *fp, const char *word );
void imc_savechar( CHAR_DATA *ch, FILE *fp );
void imc_freechardata( CHAR_DATA *ch );
void imc_loop( void );
IMC_CHANNEL *imc_findchannel( char *name ); /* Externalized for comm.c spamguard checks */
void imc_register_packet_handler( char *name, PACKET_FUN *func );
#if defined(_DISKIO_H_)
void imc_load_pfile( CHAR_DATA *ch, char *tag, int num, char *line );
void imc_save_pfile( struct CHAR_DATA *ch, FBFILE *fp );
#endif

#endif