直接放代码了:
"/feature/mxp.c"
#include <mxp.h>
private nosave mapping mxp_version_info;
private nosave mapping mxp_support_info;
public mixed QueryMXP(){
if(!this_player()) return 0;
return has_mxp(this_player());
}
public void init_mxp() {
if (!interactive() || !QueryMXP())
return;
mxp_version_info = ([]);
mxp_support_info = ([ MXP_SUPPORT_ENABLED: ({}), MXP_SUPPORT_DISABLED: ({}) ]);
efun::write(process_mxp(MXPTAG("!-- Set up MXP elements --"), QueryMXP()));
efun::write(process_mxp(MXPTAG("!ELEMENT RNum FLAG=\"RoomNum\" ATT=\"id\" EMPTY"), QueryMXP()));
efun::write(process_mxp(MXPTAG("!ELEMENT RName FLAG=\"RoomName\""), QueryMXP()));
efun::write(process_mxp(MXPTAG("!ELEMENT RDesc FLAG=\"RoomDesc\""), QueryMXP()));
efun::write(process_mxp(MXPTAG("!ELEMENT RExits FLAG=\"RoomExit\""), QueryMXP()));
efun::write(process_mxp(MXPTAG("!ELEMENT Prompt FLAG=\"Prompt\""), QueryMXP()));
efun::write(process_mxp(MXPTAG("!ELEMENT Ex \"<send>\""), QueryMXP()));
}
public void SetMXPVersion(mapping m) {
if (!mxp_version_info)
mxp_version_info = ([]);
mxp_version_info = m;
}
public void SetEnabledMXPSupportInfo(string *s) {
if (!mxp_support_info)
mxp_support_info = ([]);
mxp_support_info[MXP_SUPPORT_ENABLED] = s;
}
public void SetDisabledMXPSupportInfo(string *s ) {
if (!mxp_support_info)
mxp_support_info = ([]);
mxp_support_info[MXP_SUPPORT_DISABLED] = s;
}
public mapping QueryMXPVersion() {
return mxp_version_info || ([]);
}
public mapping QueryMXPSupportInfo() {
return mxp_support_info || ([ MXP_SUPPORT_ENABLED: ({}), MXP_SUPPORT_DISABLED: ({}) ]);
}
"/adm/simul_efun/process_mxp.c"
#ifndef MXP_H
#include <mxp.h>
#endif
/*
** Function: process_mxp
**
** Purpose: Process MXP.
**
** Parameters: string msg, the msg to transform
**
** Returns: string
*/
public string process_mxp(string msg, int does_mxp) {
int line = 0;
int length = 0;
int i = 0;
int inTag = 0;
int inEntity = 0;
string *original_lines = explode(msg, "\n");
string *processed_lines = allocate(sizeof(original_lines));
if(!does_mxp) return msg;
for (line = 0; line < sizeof(original_lines); line++) {
processed_lines[line] = does_mxp ? MXPMODE(1) : "";
length = sizeof(original_lines[line]);
for (i = 0; i < length; i++) {
if (inTag) { /* in a tag, eg. <send> */
if (original_lines[line][i..i] == MXP_END) {
inTag = 0;
if (does_mxp) {
processed_lines[line] += ">";
}
} else if (does_mxp) { /* copy tag only when MXP does_mxp */
processed_lines[line] += original_lines[line][i..i];
}
} else if (inEntity) { /* in a tag, eg. <send> */
if (does_mxp) { /* copy tag only when MXP does_mxp */
processed_lines[line] += original_lines[line][i..i];
}
if (original_lines[line][i..i] == ";") {
inEntity = 0;
}
} else {
if (original_lines[line][i..i] == MXP_BEG) {
inTag = 1;
if (does_mxp) {
processed_lines[line] += "<";
}
} else if (original_lines[line][i..i] == MXP_END) { /* should not get this case */
processed_lines[line] += ">";
} else if (original_lines[line][i..i] == MXP_AMP) {
inEntity = 1;
if (does_mxp) {
processed_lines[line] += "<";
}
} else if (does_mxp) {
if (original_lines[line][i..i] == "<") {
processed_lines[line] += "<";
} else if (original_lines[line][i..i] == ">") {
processed_lines[line] += ">";
} else if (original_lines[line][i..i] == "&") {
processed_lines[line] += "&";
} else if (original_lines[line][i..i] == "\"") {
processed_lines[line] += """;
} else {
processed_lines[line] += original_lines[line][i..i];
}
} else { /* not MXP - just copy character */
processed_lines[line] += original_lines[line][i..i];
}
}
}
}
return implode(processed_lines, "\n");
}
以上sefun需要在simul_efun.c中#include "/adm/simul_efun/process_mxp.c"
"/feature/message.c"
// message.c
#include <ansi.h>
#include <dbase.h>
#include <mxp.h>
#define MAX_MSG_BUFFER 500
#define TOMXP (int)this_object()->QueryMXP()
nosave string *msg_buffer = ({});
void receive_message(string msgclass, string msg)
{
string subclass, *ch;
if( !interactive(this_object()) ) {
this_object()->relay_message(msgclass, msg);
return;
}
if( sscanf(msgclass, "%s:%s", subclass, msgclass)==2 ) {
switch(subclass) {
case "channel":
if( !pointerp(ch = query("channels"))
|| member_array(msgclass, ch)==-1 )
return;
break;
case "outdoor":
if( !environment() || !environment()->query("outdoors") )
return;
break;
default:
error("Message: Invalid Subclass " + subclass + ".\n");
}
}
if( query_temp("block_msg/all") || query_temp("block_msg/" + msgclass) )
return;
if( in_input(this_object()) || in_edit(this_object()) ) {
if( sizeof(msg_buffer) < MAX_MSG_BUFFER )
msg_buffer += ({ msg });
} else
receive( process_mxp(msg, TOMXP) );
}
void write_prompt()
{
if( sizeof(msg_buffer) ) {
receive(BOLD "[输入时暂存讯息]\n" NOR);
for(int i=0; i<(sizeof(msg_buffer)>MAX_MSG_BUFFER? MAX_MSG_BUFFER:sizeof(msg_buffer)); i++)
receive(msg_buffer[i]);
msg_buffer = ({});
}
receive(process_mxp(sprintf("%s%s%s", MXPTAG("Prompt"), "> ", MXPTAG("/Prompt")), TOMXP));
}
void receive_snoop(string msg)
{
receive("%" + msg);
}
"/include/mxp.h"
#ifndef MXP_H
#define MXP_H
#define MXP_SUPPORT_ENABLED "mxp_enabled_features"
#define MXP_SUPPORT_DISABLED "mxp_disabled_features"
/* strings */
#define MXP_BEG "\x03"
#define MXP_END "\x04"
#define MXP_AMP "\x05"
/* characters */
#define MXP_BEGc '\x03'
#define MXP_ENDc '\x04'
#define MXP_AMPc '\x05'
/* constructs an MXP tag with < and > around it */
#define MXPTAG(arg) sprintf("%s%s%s", MXP_BEG, arg, MXP_END)
#define ESC1 "\x1B" /* esc character */
#define MXPMODE(arg) sprintf("%s[%dz", ESC1, arg)
#endif // MXP_H
cmds look.c 中需要改造部分如下:
int look_room(object me, object env) {
int i;
object *inv;
mapping exits;
string /*roomdesc,*/ str, *dirs;
if(!env) {
write("你的四周灰蒙蒙地一片,什麽也没有。\n");
return 1;
}
str=sprintf( "%s - %s\n", env->query("short"), wizardp(me)? file_name(env)+sprintf(" - (%d,%d,%d)",env->query("coor/x"), env->query("coor/y"),env->query("coor/z")): sprintf("(%d,%d,%d)",env->query("coor/x"), env->query("coor/y"),env->query("coor/z")));
str=MXPTAG("RDesc")+str+MXPTAG("/RDesc");
write(str);
if( me->query("env/show_way") && ! me->query("env/brief"))
realtime_map(me, env);
// room descriptions.
str = sprintf( " %s%s",
env->long(),
env->query("outdoors")? NATURE_D->outdoor_room_description() : "" );
str=MXPTAG("RDesc")+str+MXPTAG("/RDesc");
// exits.
if(mapp(exits = env->query("exits"))) {
dirs = keys(exits);
for(i=0; i<sizeof(dirs); i++) {
if((int)env->query_door(dirs[i], "status") & DOOR_CLOSED ) {
dirs[i] = 0;
}
}
dirs -= ({ 0 });
if(sizeof(dirs)==0) {
str += " 这里没有任何明显的出路。\n";
} else if(sizeof(dirs)==1) {
str += " 这里唯一的出口是 " + BOLD +MXPTAG("RExits")+MXPTAG("Ex")+ dirs[0]+MXPTAG("/Ex")+ MXPTAG("/RExits") + NOR + "。\n";
} else {
dirs = map(dirs, (: MXPTAG("Ex") + $1 + MXPTAG("/Ex") :));
str += sprintf(" 这里明显的出口是 " + BOLD + "%s" + NOR +
" 和 " + BOLD + "%s" + NOR + "。\n",
MXPTAG("RExits")+implode(dirs[0..sizeof(dirs)-2], "、")+ MXPTAG("/RExits"), MXPTAG("RExits")+dirs[sizeof(dirs)-1]+MXPTAG("/RExits"));
}
} else {
str += " 这里没有任何明显的出路。\n";
}
// all things in the room.
inv = all_inventory(env);
if (!env->query("brief_objects"))
for(i=0; i<sizeof(inv); i++) {
if(inv[i]==me || inv[i]->query("no_shown") || !me->visible(inv[i])) {
continue;
}
if (inv[i]->query_temp("team_name"))
str += " " + inv[i]->short() + WHT" < "+inv[i]->query_temp("team_name")+" >\n"NOR;
else
str += " " + inv[i]->short() + "\n";
}
str=MXPTAG("RDesc")+str+MXPTAG("/RDesc");
write(str);
return 1;
}
"/adm/daemons/logind.c"
// enter_world 部分 `exec(user, ob);` 后增加
user->init_mxp();
user object 中 inherit "feature/mxp";
#include <origin.h>
#include <user.h>
#include <room.h>
#include <ansi.h>
inherit CHARACTER;
inherit F_MASTER;
inherit F_AUTOLOAD;
inherit F_SAVE;
inherit "feature/mxp";
nosave int last_age_set;
void autosave();
void create() {
::create();
set_name("使用者物件", ({ "user object", "user", "object" }) );
}