/****************************************************************************
* _______ _ ______ _______ _______ ______ *
* ( ____ \( \ ( __ \ |\ /|( ___ )( )|\ /|( __ \ *
* | ( \/| ( | ( \ )| ) ( || ( ) || () () || ) ( || ( \ ) *
* | (__ | | | | ) || (___) || (___) || || || || | | || | ) | *
* | __) | | | | | || ___ || ___ || |(_)| || | | || | | | *
* | ( | | | | ) || ( ) || ( ) || | | || | | || | ) | *
* | (____/\| (____/\| (__/ )| ) ( || ) ( || ) ( || (___) || (__/ ) *
* (_______/(_______/(______/ |/ \||/ \||/ \|(_______)(______/ *
* +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ *
* |T|h|e| |O|a|k|l|a|n|d| |C|h|r|o|n|i|c|l|e|s| *
* +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ *
* ------------------------------------------------------------------------- *
* EldhaMUD code (C) 2003-2005 by Robert Powell (Tommi) *
* EldhaMUD Team: Celest, Altere and Krelowyn *
* ------------------------------------------------------------------------- *
* *
****************************************************************************/
/******************************************************
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 "./Headers/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 );
}