Message
| Changes to SmaugFuss 1.9 source
Below are the "diffs" of the changes I made to the stock SmaugFuss 1.9 source to implement this system:
diff --git a/src/act_info.c b/src/act_info.c
index c097575..5f0ddce 100644
--- a/src/act_info.c
+++ b/src/act_info.c
@@ -35,7 +35,6 @@ bool check_parse_name( const char *name, bool newchar );
void show_char_to_char_0( CHAR_DATA * victim, CHAR_DATA * ch );
void show_char_to_char_1( CHAR_DATA * victim, CHAR_DATA * ch );
void show_char_to_char( CHAR_DATA * list, CHAR_DATA * ch );
-bool check_blind( CHAR_DATA * ch );
void show_condition( CHAR_DATA * ch, CHAR_DATA * victim );
/*
diff --git a/src/comm.c b/src/comm.c
index 88f0d76..a45bdbf 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -64,6 +64,8 @@ void shutdown_checkpoint( void );
#include <netdb.h>
#endif
+#define MUD_SPECIFIC '\x66'
+
#ifdef IMC
void imc_delete_info( void );
void free_imcdata( bool complete );
@@ -92,6 +94,7 @@ void free_all_reserved( void );
const char echo_off_str[] = { ( char )IAC, ( char )WILL, TELOPT_ECHO, '\0' };
const char echo_on_str[] = { ( char )IAC, ( char )WONT, TELOPT_ECHO, '\0' };
const char go_ahead_str[] = { ( char )IAC, ( char )GA, '\0' };
+const char want_server_status[] = { ( char )IAC, ( char )WILL, MUD_SPECIFIC, '\0' };
void save_sysdata( SYSTEM_DATA sys );
@@ -1037,6 +1040,7 @@ void new_descriptor( int new_desc )
dnew->ifd = -1; /* Descriptor pipes, used for DNS resolution and such */
dnew->ipid = -1;
dnew->can_compress = FALSE;
+ dnew->want_server_status = false;
CREATE( dnew->mccp, MCCP, 1 );
CREATE( dnew->outbuf, char, dnew->outsize );
@@ -1086,6 +1090,11 @@ void new_descriptor( int new_desc )
write_to_buffer( dnew, will_compress2_str, 0 );
/*
+ * extra MUD status
+ */
+ write_to_buffer( dnew, want_server_status, 0 );
+
+ /*
* Send the greeting.
*/
{
@@ -1402,6 +1411,16 @@ void read_from_buffer( DESCRIPTOR_DATA * d )
else if( d->inbuf[i - 1] == ( signed char )DONT )
compressEnd( d );
}
+ else if( d->inbuf[i] == ( signed char )MUD_SPECIFIC )
+ {
+ if( d->inbuf[i - 1] == ( signed char )DO )
+ {
+ d->want_server_status = true;
+ write_to_descriptor(d, "\xFF\xFA\x66tt=\"version\";version=1.0;\xFF\xF0", 0);
+ }
+ else if( d->inbuf[i - 1] == ( signed char )DONT )
+ d->want_server_status = false;
+ }
}
else if( d->inbuf[i] == '\b' && k > 0 )
--k;
@@ -1522,6 +1541,12 @@ bool flush_buffer( DESCRIPTOR_DATA * d, bool fPrompt )
}
/*
+ * Status as a telnet message
+ */
+
+ show_status (d->character);
+
+ /*
* Short-circuit if nothing to write.
*/
if( d->outtop == 0 )
@@ -3731,6 +3756,81 @@ void display_prompt( DESCRIPTOR_DATA * d )
return;
}
+void show_status( CHAR_DATA *ch )
+{
+
+ if (WANT_TELNET_INFO (ch))
+ {
+ CHAR_DATA * victim = NULL;
+
+ if (ch->fighting)
+ victim = ch->fighting->who;
+
+ char buf[MAX_STRING_LENGTH];
+ snprintf(buf, sizeof (buf),
+ "\xFF\xFA\x66" // IAC SB 102
+ "tt=\"status\";" // transaction type: status
+ "hp=%d;maxhp=%d;" // hp points
+ "mana=%d;maxmana=%d;" // mana
+ "move=%d;maxmove=%d;" // movement
+ "xp=%d;maxxp=%d;" // experience
+ "gold=%i;" // gold
+ "level=%d;" // level
+ "combat=%s;" // in combat or not
+ "dead=%s;" // dead?
+ "poisoned=%s;", // poisoned?
+ ch->hit,
+ ch->max_hit,
+ IS_VAMPIRE( ch ) ? 0 : ch->mana,
+ IS_VAMPIRE( ch ) ? 0 : ch->max_mana,
+ ch->move,
+ ch->max_move,
+ ch->exp,
+ exp_level( ch, ch->level + 1 ) - ch->exp,
+ ch->gold,
+ ch->level,
+ (ch->fighting && ch->fighting->who) ? "true" : "false",
+ TRUE_OR_FALSE (char_died( ch )),
+ TRUE_OR_FALSE (IS_AFFECTED( ch, AFF_POISON ))
+ );
+
+ // combat info
+ if (victim)
+ {
+ const char * p = "You";
+ char * pName;
+
+ if (ch != victim)
+ {
+ if (IS_NPC( victim ) )
+ p = victim->short_descr;
+ else
+ p = victim->name;
+ }
+
+ pName = fixup_lua_strings (p);
+
+ snprintf(&buf [strlen (buf)], sizeof (buf) - strlen (buf),
+ "victim={name=%s;" // name
+ "hp=%d;maxhp=%d;" // hp points
+ "level=%d;" // level
+ "};",
+ pName,
+ victim->hit,
+ victim->max_hit,
+ victim->level
+ );
+ free (pName);
+ }
+
+ // finish telnet negotiation after the combat info
+ strncpy(&buf [strlen (buf)], "\xFF\xF0", sizeof (buf) - strlen (buf)); // IAC SE
+
+ send_to_char( buf, ch );
+ }
+
+}
+
void set_pager_input( DESCRIPTOR_DATA * d, char *argument )
{
while( isspace( *argument ) )
diff --git a/src/handler.c b/src/handler.c
index 5a1f877..deaa115 100644
--- a/src/handler.c
+++ b/src/handler.c
@@ -49,6 +49,96 @@ void delete_reset( RESET_DATA * pReset );
int trw_loops = 0;
TRV_WORLD trw_heap[TRW_MAXHEAP];
+// Author: Nick Gammon; 2nd February 2010
+// Fixup for sending Lua-style strings to client
+// Convert: \r \n double-quote IAC and ESC
+// Note that Lua expects 0x00 to be sent as \0 however since this is a
+// null-terminated string, we won't ever get 0x00
+// Also puts quotes around result to save you the trouble of doing it.
+
+char * fixup_lua_strings (const char * sce)
+ {
+ const char * p;
+ char * dest;
+ char * pd;
+ int count = 3; // allow for quotes and final 0x00 at end
+ unsigned char c;
+
+ // first work out how much memory to allocate
+ if (sce)
+ {
+ for (p = sce; *p; p++, count++)
+ {
+ c = (unsigned char) *p;
+ switch (c)
+ {
+ case '\r': // carriage-return
+ case '\n': // newline
+ case '"': // double-quote
+ count++; // becomes \r \n and \"
+ break;
+
+ case '\x1B': // ESC becomes \027
+ case '\xFF': // IAC becomes \255
+ count += 3;
+ break;
+
+ } /* end of switch on character */
+
+ } /* end of counting */
+ } // if sce not NULL
+
+ dest = (char *) malloc (count);
+ pd = dest;
+ *pd++ = '"'; // opening quote
+
+ if (sce)
+ {
+ for (p = sce; *p; p++)
+ {
+ c = (unsigned char) *p;
+ switch (c)
+ {
+ case '\r': // carriage-return
+ memcpy (pd, "\\r", 2);
+ pd += 2;
+ break;
+
+ case '\n': // newline
+ memcpy (pd, "\\n", 2);
+ pd += 2;
+ break;
+
+ case '"': // double-quote
+ memcpy (pd, "\\\"", 2);
+ pd += 2;
+ break;
+
+ case '\x1B': // ESC
+ memcpy (pd, "\\027", 4);
+ pd += 4;
+ break;
+
+ case '\xFF': // IAC
+ memcpy (pd, "\\255", 4);
+ pd += 4;
+ break;
+
+ default:
+ *pd++ = c;
+ break;
+
+ } /* end of switch on character */
+
+ } /* end of copying */
+ } // if sce not NULL
+
+ *pd++ = '"'; // closing quote
+ *pd = 0; // terminating 0x00
+
+ return dest;
+}
+
TRV_DATA *trvch_create( CHAR_DATA * ch, trv_type tp )
{
CHAR_DATA *first, *ptr;
@@ -1780,6 +1870,65 @@ void char_to_room( CHAR_DATA * ch, ROOM_INDEX_DATA * pRoomIndex )
if( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] != 0 )
++pRoomIndex->light;
+ if (WANT_TELNET_INFO (ch))
+ {
+ char buf[MAX_STRING_LENGTH];
+ bool blind = !check_blind( ch ); // true is NOT blind
+ bool dark = !xIS_SET( ch->act, PLR_HOLYLIGHT ) &&
+ !IS_AFFECTED( ch, AFF_TRUESIGHT ) &&
+ !IS_AFFECTED( ch, AFF_INFRARED ) &&
+ room_is_dark( ch->in_room );
+
+ snprintf(buf, sizeof (buf),
+ "\xFF\xFA\x66" // IAC SB 102
+ "tt=\"move\";" // transaction type: move
+ "blind=%s;" // character blind?
+ "dark=%s;", // room dark?
+ TRUE_OR_FALSE (blind),
+ TRUE_OR_FALSE (dark)
+ );
+
+ // show exits if they are not blinded and it is not dark
+ if (! (blind || dark))
+ {
+ char * pName = fixup_lua_strings (ch->in_room->name);
+ EXIT_DATA *pexit;
+
+ // if not blind or dark show them room name and vnum
+ snprintf(&buf [strlen (buf)], sizeof (buf) - strlen (buf),
+ "room=%d;name=%s;", // vnum, name
+ ch->in_room->vnum,
+ pName
+ );
+ free (pName);
+
+ strncpy(&buf [strlen (buf)], "exits={", sizeof (buf) - strlen (buf));
+
+ for( pexit = ch->in_room->first_exit; pexit; pexit = pexit->next )
+ {
+ if( pexit->to_room
+ && !IS_SET( pexit->exit_info, EX_CLOSED )
+ && ( !IS_SET( pexit->exit_info, EX_WINDOW )
+ || IS_SET( pexit->exit_info, EX_ISDOOR ) ) && !IS_SET( pexit->exit_info, EX_HIDDEN ) )
+ {
+ // WARNING - I assume dir_name gives names that are valid Lua names (which it currently does)
+ // if not you would need to use fixup_lua_strings and do something like: "[%s]=%i;"
+ snprintf(&buf [strlen (buf)], sizeof (buf) - strlen (buf),
+ "%s=%i;", // north=12345
+ dir_name[pexit->vdir],
+ pexit->vnum
+ );
+ }
+ } // end for each exit
+ strncpy(&buf [strlen (buf)], "};", sizeof (buf) - strlen (buf));
+ } // if not blind or dark
+
+ // finish telnet negotiation after the exits
+ strncpy(&buf [strlen (buf)], "\xFF\xF0", sizeof (buf) - strlen (buf)); // IAC SE
+
+ send_to_char( buf, ch );
+ }
+
/*
* Add the room's affects to the char.
* Even if the char died, we must do this, because the char
diff --git a/src/mapper.c b/src/mapper.c
index b947b8e..0b86ad7 100644
--- a/src/mapper.c
+++ b/src/mapper.c
@@ -55,8 +55,6 @@
#include "mud.h"
#include "mapper.h"
-bool check_blind( CHAR_DATA * ch );
-
/* The map itself */
MAP_TYPE dmap[MAPX + 1][MAPY + 1];
diff --git a/src/mud.h b/src/mud.h
index afc197e..e3ff0a0 100644
--- a/src/mud.h
+++ b/src/mud.h
@@ -802,6 +802,7 @@ struct descriptor_data
unsigned char prevcolor;
int ifd;
pid_t ipid;
+ bool want_server_status;
};
/*
@@ -3235,7 +3236,14 @@ do \
#define HAS_BODYPART(ch, part) ((ch)->xflags == 0 || IS_SET((ch)->xflags, (part)))
#define GET_TIME_PLAYED(ch) (((ch)->played + (current_time - (ch)->logon)) / 3600)
#define CAN_CAST(ch) ((ch)->Class != 2 && (ch)->Class != 3)
-
+#define WANT_TELNET_INFO(ch) \
+ (ch != NULL && \
+ !IS_NPC(ch) && \
+ !mud_down && \
+ ch->desc != NULL && \
+ ch->desc->connected == CON_PLAYING && \
+ ch->desc->want_server_status)
+#define TRUE_OR_FALSE(arg) ((arg) ? "true" : "false")
#define IS_VAMPIRE(ch) (!IS_NPC(ch) \
&& ((ch)->race==RACE_VAMPIRE \
|| (ch)->Class==CLASS_VAMPIRE))
@@ -4320,6 +4328,7 @@ char *format_obj_to_char( OBJ_DATA * obj, CHAR_DATA * ch, bool fShort );
void show_list_to_char( OBJ_DATA * list, CHAR_DATA * ch, bool fShort, bool fShowNothing );
bool is_ignoring( CHAR_DATA * ch, CHAR_DATA * ign_ch );
void show_race_line( CHAR_DATA * ch, CHAR_DATA * victim );
+bool check_blind( CHAR_DATA * ch );
/* act_move.c */
void clear_vrooms args( ( void ) );
@@ -4439,6 +4448,7 @@ void pager_printf( CHAR_DATA * ch, const char *fmt, ... ) __attribute__ ( ( form
void pager_printf_color( CHAR_DATA * ch, const char *fmt, ... ) __attribute__ ( ( format( printf, 2, 3 ) ) );
void act( short AType, const char *format, CHAR_DATA * ch, const void *arg1, const void *arg2, int type );
const char *myobj( OBJ_DATA * obj );
+void show_status( CHAR_DATA *ch );
/* reset.c */
RD *make_reset( char letter, int extra, int arg1, int arg2, int arg3 );
@@ -4665,6 +4675,7 @@ int fread_imm_host( FILE * fp, IMMORTAL_HOST * data );
void do_write_imm_host( void );
/* handler.c */
+char * fixup_lua_strings (const char * sce);
void free_obj( OBJ_DATA * obj );
CHAR_DATA *carried_by( OBJ_DATA * obj );
AREA_DATA *get_area_obj( OBJ_INDEX_DATA * obj );
diff --git a/src/update.c b/src/update.c
index fad7a24..ac6acab 100644
--- a/src/update.c
+++ b/src/update.c
@@ -1279,6 +1279,7 @@ void char_update( void )
else if( ch == ch_save && IS_SET( sysdata.save_flags, SV_AUTO ) && ++save_count < 10 ) /* save max of 10 per tick */
save_char_obj( ch );
}
+ show_status (ch);
}
trworld_dispose( &lc );
}
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|