pennmush/game/data/
pennmush/game/log/
pennmush/game/save/
pennmush/game/txt/evt/
pennmush/game/txt/nws/
pennmush/os2/
pennmush/po/
pennmush/win32/msvc.net/
pennmush/win32/msvc6/
/*------------------------------------------------------------------
 * Header file for Javelin's extended @chat system
 * Based on the Battletech MUSE comsystem ported to PennMUSH by Kalkin
 *
 * Why:
 *  In the old system, channels were represented by bits set in a
 *  4-byte int on the db object. This had disadvantages - a limit
 *  of 32 channels, and players could find themselves on null channels.
 *  In addition, the old system required recompiles to permanently
 *  add channels, since the chaninfo was in the source.
 * How:
 *  Channels are a structure in a linked list.
 *  Each channel stores a whole bunch of info, including who's
 *  on it.
 *  We read/write this list using a chatdb file.
 *  We also maintain a linked list of channels that the user is
 *   connected to on the db object, which we set up at load time.
 *
 * User interface:
 * @chat channel = message
 * +channel message
 * @channel/on channel [= player] (or @channel channel = on)  do_channel()
 * @channel/off channel [= player] do_channel()
 * @channel/who channel do_channel()
 * @channel/title channel=title do_chan_title()
 * @channel/list do_chan_list()
 * @channel/add channel do_chan_admin()
 * @channel/priv channel = <privlist>  do_chan_admin()
 *  Privlist being: wizard, admin, private, moderated, etc.
 * @channel/joinlock channel = lock
 * @channel/speaklock channel = lock
 * @channel/modlock channel = lock
 * @channel/delete channel
 * @channel/quiet channel = yes/no
 * @channel/wipe channel
 * @channel/buffer channel = <maxlines>
 * @channel/recall channel [= <lines>]
 *
 *------------------------------------------------------------------*/

#ifndef __EXTCHAT_H
#define __EXTCHAT_H


#include "boolexp.h"
#include "bufferq.h"

#define CU_TITLE_LEN 80

/** A channel user.
 * This structure represents an object joined to a chat channel.
 * Each chat channel maintains a linked list of users.
 */
struct chanuser {
  dbref who;			/**< Dbref of joined object */
  long int type;		/**< Bitflags for this user */
  char title[CU_TITLE_LEN];	/**< User's channel title */
  struct chanuser *next;	/**< Pointer to next user in list */
};

/* Flags and macros for channel users */
#define CU_QUIET    0x1		/* Do not hear connection messages */
#define CU_HIDE     0x2		/* Do not appear on the user list */
#define CU_GAG      0x4		/* Do not hear any messages */
#define CU_DEFAULT_FLAGS 0x0

/* channel_broadcast flags */
#define CB_CHECKQUIET 0x1	/* Check for quiet flag on recipients */
#define CB_NOSPOOF    0x2	/* Use nospoof emits */
#define CB_PRESENCE   0x4	/* This is a presence message, not sound */

#define CUdbref(u) ((u)->who)
#define CUtype(u) ((u)->type)
#define CUtitle(u) ((u)->title)
#define CUnext(u) ((u)->next)
#define Chanuser_Quiet(u)       (CUtype(u) & CU_QUIET)
#define Chanuser_Hide(u) ((CUtype(u) & CU_HIDE) || (IsPlayer(CUdbref(u)) && hidden(CUdbref(u))))
#define Chanuser_Gag(u) (CUtype(u) & CU_GAG)

/* This is a chat channel */
#define CHAN_NAME_LEN 31
#define CHAN_TITLE_LEN 256
/** A chat channel.
 * This structure represents a MUSH chat channel. Channels are organized
 * into a sorted linked list.
 */
struct channel {
  char name[CHAN_NAME_LEN];	/**< Channel name */
  char title[CHAN_TITLE_LEN];	/**< Channel description */
  long int type;		/**< Channel flags */
  long int cost;		/**< What it cost to make this channel */
  long int creator;		/**< This is who paid the cost for the channel */
  long int num_users;		/**< Number of connected users */
  long int max_users;		/**< Maximum allocated users */
  struct chanuser *users;	/**< Linked list of current users */
  long int num_messages;	/**< How many messages handled by this chan since startup */
  boolexp joinlock;	/**< Who may join */
  boolexp speaklock;	/**< Who may speak */
  boolexp modifylock;	/**< Who may change things and boot people */
  boolexp seelock;	/**< Who can see this in a list */
  boolexp hidelock;	/**< Who may hide from view */
  struct channel *next;		/**< Next channel in linked list */
  BUFFERQ *bufferq;		/**< Pointer to channel recall buffer queue */
};

/** A list of channels on an object.
 * This structure is a linked list of channels that is associated
 * with each object
 */
struct chanlist {
  CHAN *chan;			/**< Channel data */
  struct chanlist *next;	/**< Next channel in list */
};

#define Chanlist(x) ((struct chanlist *)get_objdata(x, "CHANNELS"))
#define s_Chanlist(x, y) set_objdata(x, "CHANNELS", (void *)y)

/** A structure for passing channel data to notify_anything */
struct na_cpass {
  CHANUSER *u;		  /**< Pointer to channel user */
  int checkquiet;	    /**< Should quiet property be checked? */
};


/* Channel type flags and macros */
#define CHANNEL_PLAYER  0x1	/* Players may join */
#define CHANNEL_OBJECT  0x2	/* Objects may join */
#define CHANNEL_DISABLED 0x4	/* Channel is turned off */
#define CHANNEL_QUIET   0x8	/* No broadcasts connect/disconnect */
#define CHANNEL_ADMIN   0x10	/* Wizard and royalty only ok */
#define CHANNEL_WIZARD  0x20	/* Wizard only ok */
#define CHANNEL_CANHIDE 0x40	/* Can non-DARK Wizards hide here? */
#define CHANNEL_OPEN    0x80	/* Can you speak if you're not joined? */
#define CHANNEL_NOTITLES 0x100	/* Don't show titles of speakers */
#define CHANNEL_NONAMES 0x200	/* Don't show names of speakers */
#define CHANNEL_NOCEMIT 0x400	/* Disallow @cemit */
#define CHANNEL_DEFAULT_FLAGS   (CHANNEL_PLAYER)
#define CL_JOIN 0x1
#define CL_SPEAK 0x2
#define CL_MOD 0x4
#define CL_SEE 0x8
#define CL_HIDE 0x10
#define CHANNEL_COST (options.chan_cost)
#define MAX_PLAYER_CHANS (options.max_player_chans)
#define MAX_CHANNELS (options.max_channels)

#define ChanName(c) ((c)->name)
#define ChanType(c) ((c)->type)
#define ChanTitle(c) ((c)->title)
#define ChanCreator(c) ((c)->creator)
#define ChanCost(c) ((c)->cost)
#define ChanNumUsers(c) ((c)->num_users)
#define ChanMaxUsers(c) ((c)->max_users)
#define ChanUsers(c) ((c)->users)
#define ChanNext(c) ((c)->next)
#define ChanNumMsgs(c) ((c)->num_messages)
#define ChanJoinLock(c) ((c)->joinlock)
#define ChanSpeakLock(c) ((c)->speaklock)
#define ChanModLock(c) ((c)->modifylock)
#define ChanSeeLock(c) ((c)->seelock)
#define ChanHideLock(c) ((c)->hidelock)
#define ChanBufferQ(c) ((c)->bufferq)
#define Channel_Quiet(c)        (ChanType(c) & CHANNEL_QUIET)
#define Channel_Open(c) (ChanType(c) & CHANNEL_OPEN)
#define Channel_Object(c) (ChanType(c) & CHANNEL_OBJECT)
#define Channel_Player(c) (ChanType(c) & CHANNEL_PLAYER)
#define Channel_Disabled(c) (ChanType(c) & CHANNEL_DISABLED)
#define Channel_Wizard(c) (ChanType(c) & CHANNEL_WIZARD)
#define Channel_Admin(c) (ChanType(c) & CHANNEL_ADMIN)
#define Channel_CanHide(c) (ChanType(c) & CHANNEL_CANHIDE)
#define Channel_NoTitles(c) (ChanType(c) & CHANNEL_NOTITLES)
#define Channel_NoNames(c) (ChanType(c) & CHANNEL_NONAMES)
#define Channel_NoCemit(c) (ChanType(c) & CHANNEL_NOCEMIT)
#define Chan_Ok_Type(c,o) \
        ((IsPlayer(o) && Channel_Player(c)) || \
         (IsThing(o) && Channel_Object(c)))
#define Chan_Can(p,t) \
     (!(t & CHANNEL_DISABLED) && (!(t & CHANNEL_WIZARD) || Wizard(p)) && \
      (!(t & CHANNEL_ADMIN) || Hasprivs(p) || (has_power_by_name(p,"CHAT_PRIVS",NOTYPE))))
/* Who can change channel privileges to type t */
#define Chan_Can_Priv(p,t) (Wizard(p) || Chan_Can(p,t))
#define Chan_Can_Access(c,p) (Chan_Can(p,ChanType(c)))
#define Chan_Can_Join(c,p) \
     (Chan_Can_Access(c,p) && \
     (eval_chan_lock(c,p, CLOCK_JOIN)))
#define Chan_Can_Speak(c,p) \
     (Chan_Can_Access(c,p) && \
     (eval_chan_lock(c,p, CLOCK_SPEAK)))
#define Chan_Can_Cemit(c,p) \
     (!Channel_NoCemit(c) && Chan_Can_Speak(c,p))
#define Chan_Can_Modify(c,p) \
     (Wizard(p) || (ChanCreator(c) == (p)) || \
     (!Guest(p) && Chan_Can_Access(c,p) && \
     (eval_chan_lock(c,p, CLOCK_MOD))))
#define Chan_Can_See(c,p) \
     (Hasprivs(p) || See_All(p) || (Chan_Can_Access(c,p) && \
     (eval_chan_lock(c,p, CLOCK_SEE))))
#define Chan_Can_Hide(c,p) \
     (Can_Hide(p) || (Channel_CanHide(c) && Chan_Can_Access(c,p) && \
     (eval_chan_lock(c,p, CLOCK_HIDE))))
#define Chan_Can_Nuke(c,p) (Wizard(p) || (ChanCreator(c) == (p)))
#define Chan_Can_Decomp(c,p) (See_All(p) || (ChanCreator(c) == (p)))



     /* For use in channel matching */
enum cmatch_type { CMATCH_NONE, CMATCH_EXACT, CMATCH_PARTIAL, CMATCH_AMBIG };
#define CMATCHED(i) (((i) == CMATCH_EXACT) | ((i) == CMATCH_PARTIAL))

     /* Some globals */
extern int num_channels;
extern void WIN32_CDECL channel_broadcast
  (CHAN *channel, dbref player, int flags, const char *fmt, ...)
  __attribute__ ((__format__(__printf__, 4, 5)));
extern CHANUSER *onchannel(dbref who, CHAN *c);
extern void init_chatdb(void);
extern int load_chatdb(FILE * fp);
extern int save_chatdb(FILE * fp);
extern void do_cemit
  (dbref player, const char *name, const char *msg, int noisy);
extern void do_chan_user_flags
  (dbref player, char *name, const char *isyn, int flag, int silent);
extern void do_chan_wipe(dbref player, const char *name);
extern void do_chan_lock
  (dbref player, const char *name, const char *lockstr, int whichlock);
extern void do_chan_what(dbref player, const char *partname);
extern void do_chan_desc(dbref player, const char *name, const char *title);
extern void do_chan_title(dbref player, const char *name, const char *title);
extern void do_chan_recall(dbref player, const char *name, const char *lines,
			   int quiet);
extern void do_chan_buffer(dbref player, const char *name, const char *lines);
extern void init_chat(void);
extern void do_channel
  (dbref player, const char *name, const char *target, const char *com);
extern void do_chat(dbref player, CHAN *chan, const char *arg1);
extern void do_chan_admin
  (dbref player, char *name, const char *perms, int flag);
extern enum cmatch_type find_channel(const char *p, CHAN **chan, dbref player);
extern enum cmatch_type find_channel_partial(const char *p, CHAN **chan,
					     dbref player);
extern void do_channel_list(dbref player, const char *partname);
extern int do_chat_by_name
  (dbref player, const char *name, const char *msg, int source);
extern void do_chan_decompile(dbref player, const char *name, int brief);
extern void do_chan_chown(dbref player, const char *name, const char *newowner);
extern const char *channel_description(dbref player);

enum clock_type { CLOCK_JOIN, CLOCK_SPEAK, CLOCK_SEE, CLOCK_HIDE, CLOCK_MOD };
extern int eval_chan_lock(CHAN *c, dbref p, enum clock_type type);

/** Ways to match channels by partial name */
enum chan_match_type {
  PMATCH_ALL,  /**< Match all channels */
  PMATCH_OFF,  /**< Match channels user isn't on */
  PMATCH_ON    /**< Match channels user is on */
};


#endif				/* __EXTCHAT_H */