eldhamud/boards/
eldhamud/clans/
eldhamud/classes/
eldhamud/councils/
eldhamud/deity/
eldhamud/doc/
eldhamud/doc/DIKU/
eldhamud/doc/MERC/
eldhamud/doc/mudprogs/
eldhamud/houses/
eldhamud/src/o/CVS/
//
// C Implementation: mud_mesg
//
// Description: 
//
//
// Author: robert <robert@localhost>, (C) 2005
//
//
//
/******************************************************
            Desolation of the Dragon MUD II
      (C) 2000-2003  Jesse DeFer
          http://www.dotd.com  dotd@dotd.com
 ******************************************************/
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <string.h>

#include "mud.h"

/* License:
 * 1.  This software comes with no warranty.
 * 2.  This software is free, and may not be bought or sold.
 * 3.  This software may be redistributed in source-only form, with this
 *     license intact.
 * 4.  This software may be redistributed with other software, only when
 *     all of the following are met:
 *     1) the other software is in source form,
 *     2) the other software is free,
 *     3) this license does not conflict with the other software's license
 * 5.  The comment below with the author's name must remain intact.
 */
 
/* MUD-MUD Communication via SysV IPC Message Queues
 * Allows multiple muds on the same box to share their immtalk channel
 * (and possibly other channels)
 * Author: Jesse DeFer dotd@dotd.com
 * AKA: Garil, Desolation of the Dragon II MUD - dotd.com 4000
 * Version: 1.03
 * Date: 12-2-2003 11:40MST
 */

/* Notes:
 *        The message queue is set with world read/write permissions,
 *        change this if you care.
 *
 *        Should be very easy to port to any merc derivative, and fairly
 *        easy to port to anything else.  It was written and tested on
 *        a SMAUG with modified channel code, however it should work on
 *        any SMAUG without having to modify anything but a few defines.
 *        Other muds will probably require rewriting recv_text_handler.
 *        If you re-write recv_text_handler, send it and the defines you
 *        modified to dotd@dotd.com and I'll include it in the next release.
 */

 /* Installation:
 * 1.  Customize this file, including the defines below and
 *     recv_text_handler (should be obvious what needs customizing)
 * 2.  Add a snippet like the following to your mud's channel code:
 *    if ( channel == CHANNEL_IMMTALK )
 *        mud_message(ch, channel, argument);
 * 3.  Add a snippet like the following to your mud's event loop code:
 *    mud_recv_message();
 */

/* customize these defines */
/* this should point to a file, a good file is something that doesn't change
 * very often, but is owned by you and unique, /vmlinuz is NOT a good file
 */
#define IPC_KEY_FILE "/vmlinuz"
/* the port this mud runs on */
#define my_ipc_id 4600 
/* the ports the other muds run on, you can include this port too if you want
 * and the code will skip it automatically, terminate with -1
 */
const int other_ports[] = { 4600, 4700, -1 };

/* must include two %s's the first is the name, second is what they say
 * color codes and whatnot can be added
 */
#define IMMTALK_FORMAT "&B::&W%s&B:: '%s&B'\n\r"
/* end customize these defines */

/* These should be customized if your mud doesn't have them */
#ifndef MAX_STRING_LENGTH
#define MAX_STRING_LENGTH 4096
#endif
#ifndef MAX_INPUT_LENGTH
#define MAX_INPUT_LENGTH 1024
#endif
#ifndef GET_NAME
#define GET_NAME(ch) (ch)->name
#endif
#ifndef MAX_LEVEL
#define MAX_LEVEL 1
#endif

#define MAX_MSGBUF_LENGTH 2048

key_t keyval;
int qid=-2;
struct mud_msgbuf
{
    long mtype;
    char mtext[MAX_MSGBUF_LENGTH+1];
};

void close_queue()
{
    msgctl(qid, IPC_RMID, 0);
    bug("close_queue");
}

int open_queue()
{
    struct msqid_ds qstat;
    int oldqid=qid;

    qstat.msg_qnum=0;

    if (qid==-2)
        keyval = ftok(IPC_KEY_FILE, 'm');

    if (msgctl(qid, IPC_STAT, &qstat) != -1)
    {
	if (qstat.msg_qnum > 50)
	    close_queue();
    }

    if ((qid = msgget(keyval, IPC_CREAT|0666)) == -1)
    {
        bug("Unable to msgget keyval %d.", (int)keyval);
        return -1;
    }

    if (oldqid!=qid)
    {
        sprintf(log_buf,"msgget successful, qid: %d, keyval: %d", qid, (int)keyval);
	log_string(log_buf);
        oldqid = qid;
    }

    return 1;
}

void mud_send_message(char *arg)
{
    struct mud_msgbuf qbuf;
    int x;
    
    if (open_queue()<0)
        return;

    snprintf(qbuf.mtext, MAX_MSGBUF_LENGTH, "%s", arg);
    for (x=0;other_ports[x]!=-1;x++)
    {
	if (other_ports[x] == my_ipc_id)
	    continue;

	qbuf.mtype = other_ports[x];

	if (msgsnd(qid, &qbuf, strlen(qbuf.mtext)+1, 0) == -1)
	    bug("mud_send_message: errno: %d", errno);
    }
}

void mud_message(CHAR_DATA *ch, int channel, char *arg)
{
    char tbuf[MAX_MSGBUF_LENGTH+1];
    int invis;

    invis = IS_NPC(ch) ? ch->mobinvis : ch->pcdata->wizinvis;

    snprintf(tbuf, MAX_MSGBUF_LENGTH, "%d %d %d \"%s@%d\" %s",
	     channel, invis, MAX_LEVEL,
             GET_NAME(ch),
	     my_ipc_id, arg);

    mud_send_message(tbuf);
}

void recv_text_handler(char *str)
{
    DESCRIPTOR_DATA *d;
    char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH], arg3[MAX_INPUT_LENGTH];
    char chname[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH-1];
    int channel=-1, ilevel=-1, maxlevel=-1;

    str = one_argument(str, arg1);
    str = one_argument(str, arg2);
    str = one_argument(str, arg3);
    str = one_argument(str, chname);
    channel = atoi(arg1);
    ilevel = atoi(arg2);
    maxlevel = atoi(arg3);

    if ( maxlevel < MAX_LEVEL )
	ilevel += (MAX_LEVEL - maxlevel);
    else
	ilevel -= (MAX_LEVEL - maxlevel);

    if ( ilevel < 0 )
	ilevel = 1;

    snprintf(buf, MAX_STRING_LENGTH, IMMTALK_FORMAT, capitalize(chname), str);

    for ( d = first_descriptor; d; d = d->next )
    {
        CHAR_DATA *och;

        och = d->original ? d->original : d->character;
        
        if ( !och || d->connected != CON_PLAYING ||
             IS_SET(och->deaf, channel) || get_trust(och) < ilevel )
            continue;

 /*       if ( get_trust( och ) < sysdata.think_level )
            if ( channel == CHANNEL_IMMTALK )
                continue; */
        
        set_char_color( AT_LOG, och );
        send_to_char( buf, och );
    }
}

void mud_recv_message()
{
    struct mud_msgbuf qbuf;
    int ret;

    if (open_queue()<0)
        return;

    while ((ret = msgrcv(qid, &qbuf, MAX_MSGBUF_LENGTH, my_ipc_id, IPC_NOWAIT))>0)
        recv_text_handler(qbuf.mtext);
    
    if (ret==-1 && errno!=ENOMSG)
        bug("mud_recv_message: errno: %d", errno);
}