mirror of
https://github.com/tbamud/tbamud.git
synced 2025-09-22 05:50:48 +02:00
Added various protocols.
This commit is contained in:
parent
19766c1be6
commit
4b1ea25b58
7 changed files with 2636 additions and 6 deletions
|
@ -2325,7 +2325,7 @@ void list_llog_entries(struct char_data *ch)
|
|||
i = fread(&llast, sizeof(struct last_entry), 1, fp);
|
||||
|
||||
while(!feof(fp)) {
|
||||
send_to_char(ch, "%10s\t%d\t%s\t%s", llast.username, llast.punique,
|
||||
send_to_char(ch, "%10s %d %s %s", llast.username, llast.punique,
|
||||
last_array[llast.close_type], ctime(&llast.time));
|
||||
i = fread(&llast, sizeof(struct last_entry), 1, fp);
|
||||
}
|
||||
|
|
89
src/comm.c
89
src/comm.c
|
@ -163,6 +163,7 @@ static sigfunc *my_signal(int signo, sigfunc *func);
|
|||
static RETSIGTYPE websterlink(int sig);
|
||||
static size_t proc_colors(char *txt, size_t maxlen, int parse);
|
||||
static void handle_webster_file();
|
||||
static void msdp_update(void);
|
||||
|
||||
/* externally defined functions, used locally */
|
||||
#ifdef __CXREF__
|
||||
|
@ -965,6 +966,9 @@ void heartbeat(int heart_pulse)
|
|||
if (!(heart_pulse % PULSE_VIOLENCE))
|
||||
perform_violence();
|
||||
|
||||
if (!(heart_pulse % PASSES_PER_SEC))
|
||||
msdp_update();
|
||||
|
||||
if (!(heart_pulse % (SECS_PER_MUD_HOUR * PASSES_PER_SEC))) { /* Tick ! */
|
||||
next_tick = SECS_PER_MUD_HOUR; /* Reset tick coundown */
|
||||
weather_and_time(1);
|
||||
|
@ -1334,6 +1338,12 @@ size_t vwrite_to_output(struct descriptor_data *t, const char *format, va_list a
|
|||
return (0);
|
||||
|
||||
wantsize = size = vsnprintf(txt, sizeof(txt), format, args);
|
||||
|
||||
strcpy(txt, ProtocolOutput( t, txt, (int*)&wantsize ));
|
||||
size = wantsize;
|
||||
if ( t->pProtocol->WriteOOB > 0 )
|
||||
--t->pProtocol->WriteOOB;
|
||||
|
||||
if (t->character)
|
||||
wantsize = size = proc_colors(txt, sizeof(txt), COLOR_ON(t->character));
|
||||
/* If exceeding the size of the buffer, truncate it for the overflow message */
|
||||
|
@ -1498,6 +1508,7 @@ static void init_descriptor (struct descriptor_data *newd, int desc)
|
|||
if (++last_desc == 1000)
|
||||
last_desc = 1;
|
||||
newd->desc_num = last_desc;
|
||||
newd->pProtocol = ProtocolCreate();
|
||||
}
|
||||
|
||||
static int new_descriptor(socket_t s)
|
||||
|
@ -1569,6 +1580,8 @@ static int new_descriptor(socket_t s)
|
|||
newd->next = descriptor_list;
|
||||
descriptor_list = newd;
|
||||
|
||||
ProtocolNegotiate(newd); /* <--- Add this line */
|
||||
|
||||
/* This is where the greetings are actually sent to the new player */
|
||||
/* Adjusted by Jamdog to show color codes on the greetings page */
|
||||
*greet_copy = '\0';
|
||||
|
@ -1602,14 +1615,16 @@ static int process_output(struct descriptor_data *t)
|
|||
|
||||
/* add the extra CRLF if the person isn't in compact mode */
|
||||
if (STATE(t) == CON_PLAYING && t->character && !IS_NPC(t->character) && !PRF_FLAGGED(t->character, PRF_COMPACT))
|
||||
if ( !t->pProtocol->WriteOOB )
|
||||
strcat(osb, "\r\n"); /* strcpy: OK (osb:MAX_SOCK_BUF-2 reserves space) */
|
||||
|
||||
/* add a prompt */
|
||||
if ( !t->pProtocol->WriteOOB )
|
||||
strcat(i, make_prompt(t)); /* strcpy: OK (i:MAX_SOCK_BUF reserves space) */
|
||||
|
||||
/* now, send the output. If this is an 'interruption', use the prepended
|
||||
* CRLF, otherwise send the straight output sans CRLF. */
|
||||
if (t->has_prompt) {
|
||||
if (t->has_prompt && !t->pProtocol->WriteOOB) {
|
||||
t->has_prompt = FALSE;
|
||||
result = write_to_descriptor(t->descriptor, i);
|
||||
if (result >= 2)
|
||||
|
@ -1860,6 +1875,9 @@ static int process_input(struct descriptor_data *t)
|
|||
char *ptr, *read_point, *write_point, *nl_pos = NULL;
|
||||
char tmp[MAX_INPUT_LENGTH];
|
||||
|
||||
static char read_buf[PROTOCOL_BUFFER];
|
||||
read_buf[0] = '\0';
|
||||
|
||||
/* first, find the point where we left off reading data */
|
||||
buf_length = strlen(t->inbuf);
|
||||
read_point = t->inbuf + buf_length;
|
||||
|
@ -1871,7 +1889,14 @@ static int process_input(struct descriptor_data *t)
|
|||
return (-1);
|
||||
}
|
||||
|
||||
bytes_read = perform_socket_read(t->descriptor, read_point, space_left);
|
||||
bytes_read = perform_socket_read(t->descriptor, read_buf, 2048);
|
||||
|
||||
if ( bytes_read >= 0 )
|
||||
{
|
||||
read_buf[bytes_read] = '\0';
|
||||
ProtocolInput( t, read_buf, bytes_read, t->inbuf );
|
||||
bytes_read = strlen(t->inbuf);
|
||||
}
|
||||
|
||||
if (bytes_read < 0) /* Error, disconnect them. */
|
||||
return (-1);
|
||||
|
@ -2122,6 +2147,8 @@ void close_socket(struct descriptor_data *d)
|
|||
if (d->showstr_count)
|
||||
free(d->showstr_vector);
|
||||
|
||||
ProtocolDestroy( d->pProtocol );
|
||||
|
||||
/*. Kill any OLC stuff .*/
|
||||
switch (d->connected) {
|
||||
case CON_OEDIT:
|
||||
|
@ -2793,3 +2820,61 @@ static void handle_webster_file(void) {
|
|||
send_to_char(ch, "You get this feedback from Merriam-Webster:\r\n");
|
||||
page_string(ch->desc, retval, 1);
|
||||
}
|
||||
|
||||
static void msdp_update( void )
|
||||
{
|
||||
struct descriptor_data *d;
|
||||
int PlayerCount = 0;
|
||||
|
||||
for (d = descriptor_list; d; d = d->next)
|
||||
{
|
||||
struct char_data *ch = d->character;
|
||||
if ( ch && !IS_NPC(ch) && d->connected == CON_PLAYING )
|
||||
{
|
||||
struct char_data *pOpponent = FIGHTING(ch);
|
||||
++PlayerCount;
|
||||
|
||||
MSDPSetString( d, eMSDP_CHARACTER_NAME, GET_NAME(ch) );
|
||||
MSDPSetNumber( d, eMSDP_ALIGNMENT, GET_ALIGNMENT(ch) );
|
||||
MSDPSetNumber( d, eMSDP_EXPERIENCE, GET_EXP(ch) );
|
||||
|
||||
MSDPSetNumber( d, eMSDP_HEALTH, GET_HIT(ch) );
|
||||
MSDPSetNumber( d, eMSDP_HEALTH_MAX, GET_MAX_HIT(ch) );
|
||||
MSDPSetNumber( d, eMSDP_LEVEL, GET_LEVEL(ch) );
|
||||
|
||||
MSDPSetNumber( d, eMSDP_CLASS, GET_CLASS(ch) );
|
||||
|
||||
MSDPSetNumber( d, eMSDP_MANA, GET_MANA(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MANA_MAX, GET_MAX_MANA(ch) );
|
||||
MSDPSetNumber( d, eMSDP_WIMPY, GET_WIMP_LEV(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MONEY, GET_GOLD(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MOVEMENT, GET_MOVE(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MOVEMENT_MAX, GET_MAX_MOVE(ch) );
|
||||
MSDPSetNumber( d, eMSDP_AC, compute_armor_class(ch) );
|
||||
|
||||
/* This would be better moved elsewhere */
|
||||
if ( pOpponent != NULL )
|
||||
{
|
||||
int hit_points = (GET_HIT(pOpponent) * 100) / GET_MAX_HIT(pOpponent);
|
||||
MSDPSetNumber( d, eMSDP_OPPONENT_HEALTH, hit_points );
|
||||
MSDPSetNumber( d, eMSDP_OPPONENT_HEALTH_MAX, 100 );
|
||||
MSDPSetNumber( d, eMSDP_OPPONENT_LEVEL, GET_LEVEL(pOpponent) );
|
||||
MSDPSetString( d, eMSDP_OPPONENT_NAME, PERS(pOpponent, ch) );
|
||||
}
|
||||
else /* Clear the values */
|
||||
{
|
||||
MSDPSetNumber( d, eMSDP_OPPONENT_HEALTH, 0 );
|
||||
MSDPSetNumber( d, eMSDP_OPPONENT_LEVEL, 0 );
|
||||
MSDPSetString( d, eMSDP_OPPONENT_NAME, "" );
|
||||
}
|
||||
|
||||
MSDPUpdate( d );
|
||||
}
|
||||
|
||||
/* Ideally this should be called once at startup, and again whenever
|
||||
* someone leaves or joins the mud. But this works, and it keeps the
|
||||
* snippet simple. Optimise as you see fit.
|
||||
*/
|
||||
MSSPSetPlayers( PlayerCount );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1315,6 +1315,8 @@ int enter_player_game (struct descriptor_data *d)
|
|||
/* Check for a login trigger in the players' start room */
|
||||
login_wtrigger(&world[IN_ROOM(d->character)], d->character);
|
||||
|
||||
MXPSendTag( d, "<VERSION>" ); /* <--- Add this line */
|
||||
|
||||
return load_result;
|
||||
}
|
||||
|
||||
|
|
2078
src/protocol.c
Executable file
2078
src/protocol.c
Executable file
File diff suppressed because it is too large
Load diff
453
src/protocol.h
Executable file
453
src/protocol.h
Executable file
|
@ -0,0 +1,453 @@
|
|||
/**************************************************************************
|
||||
* File: protocol.h Part of tbaMUD *
|
||||
* Usage: MXP, MSDP, ATCP, NAWS, TTYPE, CHARSET, 256-Colors *
|
||||
* Author: KaVir *
|
||||
* *
|
||||
* All rights reserved. See license.doc for complete information. *
|
||||
* *
|
||||
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
/******************************************************************************
|
||||
Set your MUD_NAME, and change descriptor_t if necessary.
|
||||
******************************************************************************/
|
||||
|
||||
#define MUD_NAME "Unknown MUD"
|
||||
|
||||
typedef struct descriptor_data descriptor_t;
|
||||
|
||||
/******************************************************************************
|
||||
Symbolic constants.
|
||||
******************************************************************************/
|
||||
|
||||
#define PROTOCOL_BUFFER 2048
|
||||
#define MAX_OUTPUT_BUFFER 8192
|
||||
|
||||
#define TELOPT_SEND 1
|
||||
#define TELOPT_ACCEPTED 2
|
||||
#define TELOPT_REJECTED 3
|
||||
|
||||
#define TELOPT_TTYPE 24
|
||||
#define TELOPT_NAWS 31
|
||||
#define TELOPT_CHARSET 42
|
||||
#define TELOPT_MSDP 69
|
||||
#define TELOPT_MSSP 70
|
||||
#define TELOPT_MCCP 86 /* This is MCCP version 2 */
|
||||
#define TELOPT_MSP 90
|
||||
#define TELOPT_MXP 91
|
||||
#define TELOPT_ATCP 200
|
||||
|
||||
#define MSDP_VAR 1
|
||||
#define MSDP_VAL 2
|
||||
#define MAX_MSDP_SIZE 100
|
||||
|
||||
#define MSSP_VAR 1
|
||||
#define MSSP_VAL 2
|
||||
|
||||
#define UNICODE_MALE 9794
|
||||
#define UNICODE_FEMALE 9792
|
||||
#define UNICODE_NEUTER 9791
|
||||
|
||||
/******************************************************************************
|
||||
Types.
|
||||
******************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
false,
|
||||
true
|
||||
} bool_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eUNKNOWN,
|
||||
eNO,
|
||||
eSOMETIMES,
|
||||
eYES
|
||||
} support_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eMSDP_NONE = -1, /* This must always be first. */
|
||||
|
||||
/* General */
|
||||
eMSDP_CHARACTER_NAME,
|
||||
eMSDP_SERVER_ID,
|
||||
eMSDP_SERVER_TIME,
|
||||
|
||||
/* Character */
|
||||
eMSDP_AFFECTS,
|
||||
eMSDP_ALIGNMENT,
|
||||
eMSDP_EXPERIENCE,
|
||||
eMSDP_EXPERIENCE_MAX,
|
||||
eMSDP_EXPERIENCE_TNL,
|
||||
eMSDP_HEALTH,
|
||||
eMSDP_HEALTH_MAX,
|
||||
eMSDP_LEVEL,
|
||||
eMSDP_RACE,
|
||||
eMSDP_CLASS,
|
||||
eMSDP_MANA,
|
||||
eMSDP_MANA_MAX,
|
||||
eMSDP_WIMPY,
|
||||
eMSDP_PRACTICE,
|
||||
eMSDP_MONEY,
|
||||
eMSDP_MOVEMENT,
|
||||
eMSDP_MOVEMENT_MAX,
|
||||
eMSDP_HITROLL,
|
||||
eMSDP_DAMROLL,
|
||||
eMSDP_AC,
|
||||
eMSDP_STR,
|
||||
eMSDP_INT,
|
||||
eMSDP_WIS,
|
||||
eMSDP_DEX,
|
||||
eMSDP_CON,
|
||||
eMSDP_STR_PERM,
|
||||
eMSDP_INT_PERM,
|
||||
eMSDP_WIS_PERM,
|
||||
eMSDP_DEX_PERM,
|
||||
eMSDP_CON_PERM,
|
||||
|
||||
/* Combat */
|
||||
eMSDP_OPPONENT_HEALTH,
|
||||
eMSDP_OPPONENT_HEALTH_MAX,
|
||||
eMSDP_OPPONENT_LEVEL,
|
||||
eMSDP_OPPONENT_NAME,
|
||||
|
||||
/* World */
|
||||
eMSDP_AREA_NAME,
|
||||
eMSDP_ROOM_EXITS,
|
||||
eMSDP_ROOM_NAME,
|
||||
eMSDP_ROOM_VNUM,
|
||||
eMSDP_WORLD_TIME,
|
||||
|
||||
/* Configuration */
|
||||
eMSDP_CLIENT_ID,
|
||||
eMSDP_CLIENT_VERSION,
|
||||
eMSDP_PLUGIN_ID,
|
||||
eMSDP_ANSI_COLORS,
|
||||
eMSDP_XTERM_256_COLORS,
|
||||
eMSDP_UTF_8,
|
||||
eMSDP_SOUND,
|
||||
eMSDP_MXP,
|
||||
|
||||
/* GUI variables */
|
||||
eMSDP_BUTTON_1,
|
||||
eMSDP_BUTTON_2,
|
||||
eMSDP_BUTTON_3,
|
||||
eMSDP_BUTTON_4,
|
||||
eMSDP_BUTTON_5,
|
||||
eMSDP_GAUGE_1,
|
||||
eMSDP_GAUGE_2,
|
||||
eMSDP_GAUGE_3,
|
||||
eMSDP_GAUGE_4,
|
||||
eMSDP_GAUGE_5,
|
||||
|
||||
eMSDP_MAX /* This must always be last */
|
||||
} variable_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
variable_t Variable; /* The enum type of this variable */
|
||||
char *pName; /* The string name of this variable */
|
||||
bool_t bString; /* Is this variable a string or a number? */
|
||||
bool_t bConfigurable; /* Can it be configured by the client? */
|
||||
bool_t bWriteOnce; /* Can only set this variable once */
|
||||
bool_t bGUI; /* It's a special GUI configuration variable */
|
||||
int Min; /* The minimum valid value or string length */
|
||||
int Max; /* The maximum valid value or string length */
|
||||
int Default; /* The default value for a number */
|
||||
const char *pDefault; /* The default value for a string */
|
||||
} variable_name_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool_t bReport; /* Is this variable being reported? */
|
||||
bool_t bDirty; /* Does this variable need to be sent again? */
|
||||
int ValueInt; /* The numeric value of the variable */
|
||||
char *pValueString; /* The string value of the variable */
|
||||
} MSDP_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *pName; /* The name of the MSSP variable */
|
||||
const char *pValue; /* The value of the MSSP variable */
|
||||
} MSSP_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int WriteOOB; /* Used internally to indicate OOB data */
|
||||
bool_t bNegotiated; /* Indicates client successfully negotiated */
|
||||
bool_t bBlockMXP; /* Used internally based on MXP version */
|
||||
bool_t bTTYPE; /* The client supports TTYPE */
|
||||
bool_t bNAWS; /* The client supports NAWS */
|
||||
bool_t bCHARSET; /* The client supports CHARSET */
|
||||
bool_t bMSDP; /* The client supports MSDP */
|
||||
bool_t bATCP; /* The client supports ATCP */
|
||||
bool_t bMSP; /* The client supports MSP */
|
||||
bool_t bMXP; /* The client supports MXP */
|
||||
support_t b256Support; /* The client supports XTerm 256 colors */
|
||||
int ScreenWidth; /* The client's screen width */
|
||||
int ScreenHeight; /* The client's screen height */
|
||||
char *pMXPVersion; /* The version of MXP supported */
|
||||
char *pLastTTYPE; /* Used for the cyclic TTYPE check */
|
||||
MSDP_t **pVariables; /* The MSDP variables */
|
||||
} protocol_t;
|
||||
|
||||
/******************************************************************************
|
||||
Protocol functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: ProtocolCreate
|
||||
*
|
||||
* Creates, initialises and returns a structure containing protocol data for a
|
||||
* single user. This should be called when the descriptor is initialised.
|
||||
*/
|
||||
protocol_t *ProtocolCreate( void );
|
||||
|
||||
/* Function: ProtocolDestroy
|
||||
*
|
||||
* Frees the memory allocated by the specified structure. This should be
|
||||
* called just before a descriptor is freed.
|
||||
*/
|
||||
void ProtocolDestroy( protocol_t *apProtocol );
|
||||
|
||||
/* Function: ProtocolNegotiate
|
||||
*
|
||||
* Negatiates with the client to see which protocols the user supports, and
|
||||
* stores the results in the user's protocol structure. Call this when you
|
||||
* wish to perform negotiation (but only call it once). It is usually called
|
||||
* either immediately after the user has connected, or just after they have
|
||||
* entered the game.
|
||||
*/
|
||||
void ProtocolNegotiate( descriptor_t *apDescriptor );
|
||||
|
||||
/* Function: ProtocolInput
|
||||
*
|
||||
* Extracts any negotiation sequences from the input buffer, and passes back
|
||||
* whatever is left for the mud to parse normally. Call this after data has
|
||||
* been read into the input buffer, before it is used for anything else.
|
||||
*/
|
||||
void ProtocolInput( descriptor_t *apDescriptor, char *apData, int aSize, char *apOut );
|
||||
|
||||
/* Function: ProtocolOutput
|
||||
*
|
||||
* This function takes a string, applies colour codes to it, and returns the
|
||||
* result. It should be called just before writing to the output buffer.
|
||||
*
|
||||
* The special character used to indicate the start of a colour sequence is
|
||||
* '\t' (i.e., a tab, or ASCII character 9). This makes it easy to include
|
||||
* in help files (as you can literally press the tab key) as well as strings
|
||||
* (where you can use \t instead). However players can't send tabs (on most
|
||||
* muds at least), so this stops them from sending colour codes to each other.
|
||||
*
|
||||
* The predefined colours are:
|
||||
*
|
||||
* n: no colour (switches colour off)
|
||||
* r: dark red R: bright red
|
||||
* g: dark green G: bright green
|
||||
* b: dark blue B: bright blue
|
||||
* y: dark yellow Y: bright yellow
|
||||
* m: dark magenta M: bright magenta
|
||||
* c: dark cyan C: bright cyan
|
||||
* w: dark white W: bright white
|
||||
* o: dark orange O: bright orange
|
||||
*
|
||||
* So for example "This is \tOorange\tn." will colour the word "orange". You
|
||||
* can add more colours yourself just by updating the switch statement.
|
||||
*
|
||||
* It's also possible to explicitly specify an RGB value, by including the four
|
||||
* character colour sequence (as used by ColourRGB) within square brackets, eg:
|
||||
*
|
||||
* This is a \t[F010]very dark green foreground\tn.
|
||||
*
|
||||
* The square brackets can also be used to send unicode characters, like this:
|
||||
*
|
||||
* Boat: \t[U9973/B]
|
||||
* Rook: \t[U9814/C]
|
||||
*
|
||||
* For example you might use 'B' to represent a boat on your ASCII map, or a 'C'
|
||||
* to represent a castle - but players with UTF-8 support would actually see the
|
||||
* appropriate unicode characters for a boat or a rook (the chess playing piece).
|
||||
*
|
||||
* The exact syntax is '\t' (tab), '[', 'U' (indicating unicode), then the decimal
|
||||
* number of the unicode character (see http://www.unicode.org/charts), then '/'
|
||||
* followed by the ASCII character/s that should be used if the client doesn't
|
||||
* support UTF-8. The ASCII sequence can be up to 7 characters in length, but in
|
||||
* most cases you'll only want it to be one or two characters (so that it has the
|
||||
* same alignment as the unicode character).
|
||||
*
|
||||
* Finally, this function also allows you to embed MXP tags. The easiest and
|
||||
* safest way to do this is via the ( and ) bracket options:
|
||||
*
|
||||
* From here, you can walk \t(north\t).
|
||||
*
|
||||
* However it's also possible to include more explicit MSP tags, like this:
|
||||
*
|
||||
* The baker offers to sell you a \t<send href="buy pie">pie\t</send>.
|
||||
*
|
||||
* Note that the MXP tags will automatically be removed if the user doesn't
|
||||
* support MXP, but it's very important you remember to close the tags.
|
||||
*/
|
||||
const char *ProtocolOutput( descriptor_t *apDescriptor, const char *apData, int *apLength );
|
||||
|
||||
/******************************************************************************
|
||||
Copyover save/load functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: CopyoverGet
|
||||
*
|
||||
* Returns the protocol values stored as a short string. If your mud uses
|
||||
* copyover, you should call this for each player and insert it after their
|
||||
* name in the temporary text file.
|
||||
*/
|
||||
const char *CopyoverGet( descriptor_t *apDescriptor );
|
||||
|
||||
/* Function: CopyoverSet
|
||||
*
|
||||
* Call this function for each player after a copyover, passing in the string
|
||||
* you added to the temporary text file. This will restore their protocol
|
||||
* settings, and automatically renegotiate MSDP/ATCP.
|
||||
*
|
||||
* Note that the client doesn't recognise a copyover, and therefore refuses to
|
||||
* renegotiate certain telnet options (to avoid loops), so they really need to
|
||||
* be saved. However MSDP/ATCP is handled through scripts, and we don't want
|
||||
* to have to save all of the REPORT variables, so it's easier to renegotiate.
|
||||
*
|
||||
* Client name and version are not saved. It is recommended you save these in
|
||||
* the player file, as then you can grep to collect client usage stats.
|
||||
*/
|
||||
void CopyoverSet( descriptor_t *apDescriptor, const char *apData );
|
||||
|
||||
/******************************************************************************
|
||||
MSDP functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: MSDPUpdate
|
||||
*
|
||||
* Call this regularly (I'd suggest at least once per second) to flush every
|
||||
* dirty MSDP variable that has been requested by the client via REPORT. This
|
||||
* will automatically use ATCP instead if MSDP is not supported by the client.
|
||||
*/
|
||||
void MSDPUpdate( descriptor_t *apDescriptor );
|
||||
|
||||
/* Function: MSDPSend
|
||||
*
|
||||
* Send the specified MSDP variable to the player. You shouldn't ever really
|
||||
* need to do this manually, except perhaps when debugging something. This
|
||||
* will automatically use ATCP instead if MSDP is not supported by the client.
|
||||
*/
|
||||
void MSDPSend( descriptor_t *apDescriptor, variable_t aMSDP );
|
||||
|
||||
/* Function: MSDPSendPair
|
||||
*
|
||||
* Send the specified strings to the user as an MSDP variable/value pair. This
|
||||
* will automatically use ATCP instead if MSDP is not supported by the client.
|
||||
*/
|
||||
void MSDPSendPair( descriptor_t *apDescriptor, const char *apVariable, const char *apValue );
|
||||
|
||||
/* Function: MSDPSetNumber
|
||||
*
|
||||
* Call this whenever an MSDP integer variable has changed. The easiest
|
||||
* approach is to send every MSDP variable within an update function (and
|
||||
* this is what the snippet does by default), but if the variable is only
|
||||
* set in one place you can just move its MDSPSend() call to there.
|
||||
*
|
||||
* You can also this function for bools, chars, enums, short ints, etc.
|
||||
*/
|
||||
void MSDPSetNumber( descriptor_t *apDescriptor, variable_t aMSDP, int aValue );
|
||||
|
||||
/* Function: MSDPSetString
|
||||
*
|
||||
* Call this whenever an MSDP string variable has changed. The easiest
|
||||
* approach is to send every MSDP variable within an update function (and
|
||||
* this is what the snippet does by default), but if the variable is only
|
||||
* set in one place you can just move its MDSPSend() call to there.
|
||||
*/
|
||||
void MSDPSetString( descriptor_t *apDescriptor, variable_t aMSDP, char *apValue );
|
||||
|
||||
/******************************************************************************
|
||||
MSSP functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: MSSPSetPlayers
|
||||
*
|
||||
* Stores the current number of players. The first time it's called, it also
|
||||
* stores the uptime.
|
||||
*/
|
||||
void MSSPSetPlayers( int aPlayers );
|
||||
|
||||
/******************************************************************************
|
||||
MXP functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: MXPCreateTag
|
||||
*
|
||||
* Puts the specified tag into a secure line, if MXP is supported. If the user
|
||||
* doesn't support MXP they will see the string unchanged, meaning they will
|
||||
* see the <send> tags or whatever. You should therefore check for support and
|
||||
* provide a different sequence for other users, or better yet just embed MXP
|
||||
* tags for the ProtocolOutput() function.
|
||||
*/
|
||||
char *MXPCreateTag( descriptor_t *apDescriptor, char *apTag );
|
||||
|
||||
/* Function: MXPSendTag
|
||||
*
|
||||
* This works like MXPCreateTag, but instead of returning the string it sends
|
||||
* it directly to the user. This is mainly useful for the <VERSION> tag.
|
||||
*/
|
||||
void MXPSendTag( descriptor_t *apDescriptor, char *apTag );
|
||||
|
||||
/******************************************************************************
|
||||
Sound functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: SoundSend
|
||||
*
|
||||
* Sends the specified sound trigger to the player, using MSDP or ATCP if
|
||||
* supported, MSP if not. The trigger string itself is a relative path and
|
||||
* filename, eg: SoundSend( pDesc, "monster/growl.wav" );
|
||||
*/
|
||||
void SoundSend( descriptor_t *apDescriptor, const char *apTrigger );
|
||||
|
||||
/******************************************************************************
|
||||
Colour functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: ColourRGB
|
||||
*
|
||||
* Returns a colour as an escape code, based on the RGB value provided. The
|
||||
* string must be four characters, where the first is either 'f' for foreground
|
||||
* or 'b' for background (case insensitive), and the other three characters are
|
||||
* numeric digits in the range 0 to 5, representing red, green and blue.
|
||||
*
|
||||
* For example "F500" returns a red foreground, "B530" an orange background,
|
||||
* and so on. An invalid colour will clear whatever you've set previously.
|
||||
*
|
||||
* If the user doesn't support XTerm 256 colours, this function will return the
|
||||
* best-fit ANSI colour instead.
|
||||
*
|
||||
* If you wish to embed colours in strings, use ProtocolOutput().
|
||||
*/
|
||||
const char *ColourRGB( descriptor_t *apDescriptor, const char *apRGB );
|
||||
|
||||
/******************************************************************************
|
||||
Unicode (UTF-8 conversion) functions.
|
||||
******************************************************************************/
|
||||
|
||||
/* Function: UnicodeGet
|
||||
*
|
||||
* Returns the UTF-8 sequence for the specified unicode value.
|
||||
*/
|
||||
char *UnicodeGet( int aValue );
|
||||
|
||||
/* Function: UnicodeAdd
|
||||
*
|
||||
* Adds the UTF-8 sequence for the specified unicode value onto the end of the
|
||||
* string, without adding a NUL character at the end.
|
||||
*/
|
||||
void UnicodeAdd( char **apString, int aValue );
|
||||
|
||||
#endif // PROTOCOL_H
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef _STRUCTS_H_
|
||||
#define _STRUCTS_H_
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
/** Intended use of this macro is to allow external packages to work with a
|
||||
* variety of versions without modifications. For instance, an IS_CORPSE()
|
||||
* macro was introduced in pl13. Any future code add-ons could take into
|
||||
|
@ -1129,6 +1131,7 @@ struct descriptor_data
|
|||
struct descriptor_data *snoop_by; /**< And who is snooping this char */
|
||||
struct descriptor_data *next; /**< link to next descriptor */
|
||||
struct oasis_olc_data *olc; /**< OLC info */
|
||||
protocol_t *pProtocol;
|
||||
};
|
||||
|
||||
/* other miscellaneous structures */
|
||||
|
|
15
src/utils.c
15
src/utils.c
|
@ -1299,6 +1299,7 @@ IDXTYPE atoidx( const char *str_to_conv )
|
|||
next line will start with the same color.
|
||||
Ends every line with @n to prevent color bleeds.
|
||||
*/
|
||||
#define isspace_ignoretabs(c) ((c)!='\t' && isspace(c))
|
||||
char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad)
|
||||
{
|
||||
static char ret[MAX_STRING_LENGTH];
|
||||
|
@ -1316,17 +1317,17 @@ char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad)
|
|||
/* Split into lines, including convert \\ into \r\n */
|
||||
while(*sp) {
|
||||
/* eat leading space */
|
||||
while(*sp && isspace(*sp)) sp++;
|
||||
while(*sp && isspace_ignoretabs(*sp)) sp++;
|
||||
/* word begins */
|
||||
wp = sp;
|
||||
wlen = 0;
|
||||
while(*sp) { /* Find the end of the word */
|
||||
if(isspace(*sp)) break;
|
||||
if(isspace_ignoretabs(*sp)) break;
|
||||
if(*sp=='\\' && sp[1] && sp[1]=='\\') {
|
||||
if(sp!=wp)
|
||||
break; /* Finish dealing with the current word */
|
||||
sp += 2; /* Eat the marker and any trailing space */
|
||||
while(*sp && isspace(*sp)) sp++;
|
||||
while(*sp && isspace_ignoretabs(*sp)) sp++;
|
||||
wp = sp;
|
||||
/* Start a new line */
|
||||
if(hpad)
|
||||
|
@ -1345,6 +1346,14 @@ char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad)
|
|||
if (*sp=='@' && (sp[1]!=*sp)) /* Color code, not @@ */
|
||||
last_color = sp[1];
|
||||
sp += 2; /* Eat the whole code regardless */
|
||||
} else if (*sp=='\t'&&sp[1]) {
|
||||
char MXPcode = sp[1]=='[' ? ']' : sp[1]=='<' ? '>' : '\0';
|
||||
sp += 2; /* Eat the code */
|
||||
if (MXPcode)
|
||||
{
|
||||
while (*sp!='\0'&&*sp!=MXPcode)
|
||||
++sp; /* Eat the rest of the code */
|
||||
}
|
||||
} else {
|
||||
wlen++;
|
||||
sp++;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue