Go to the documentation of this file.
78 "You can't do that to yourself.");
83 "That player is in no state for that right now.");
96 if (!
pl->stack_items || !
pl->stack_position) {
102 pl->stack_position--;
104 "Popped item from stack, %d left.",
123 if (!
pl->stack_position) {
132 "Stacked item was removed!");
151 if (!
pl->stack_items) {
162 pl->stack_items[
pl->stack_position] =
item;
164 "Item stacked as %d.",
166 pl->stack_position++;
197 int item_tag, item_position;
215 if (sscanf(*
params,
"%d", &item_tag)) {
243 if (sscanf(*
params,
"$%d", &item_position)) {
252 if (item_position >=
pl->stack_position) {
256 "No such stack item %d!",
266 "Stack item %d was removed.",
277 if (!strncmp(*
params,
"me", 2)) {
311 "loadtest will stress server through teleporting at different map places. "
312 "Use at your own risk. Very long loop used so server may have to be reset. "
313 "type loadtest TRUE to run");
319 if (strncmp(
params,
"TRUE", 4))
334 op->contr->hidden = 0;
338 "You are no longer hidden from other players");
341 "%s has entered the game.",
op->name);
353 if (
op->contr->hidden) {
358 "The Dungeon Master has arrived!");
361 op->contr->hidden = 1;
363 "Other players will no longer see you.");
368 "The Dungeon Master is gone...");
372 "%s leaves the game.",
423 if (*
params ==
'\0' || !(
str =
const_cast<char *
>(strchr(
params,
' ')))) {
425 "Usage: set_god player god");
433 "Set whose god - can not find object %s?",
444 "%s is not a player - can not change its god",
478 "%s is kicked out of the game.",
510 "Usage: banish <player>.");
520 if ((banishfile = fopen(
buf,
"a")) == NULL) {
523 "Could not find banish_file.");
532 fprintf(banishfile,
"# %s (%s) banned by %s at %s\n",
pl->ob->name,
pl->socket->host,
op->name, ctime(&
now));
533 fprintf(banishfile,
"*@%s\n",
pl->socket->host);
536 LOG(
llevDebug,
"! %s banned %s from IP: %s.\n",
op->name,
pl->ob->name,
pl->socket->host);
543 "%s banishes %s from the land!",
544 op->name,
pl->ob->name);
575 "Overlay save error!");
578 "Current map has been saved as an overlay.");
598 "Overlay successfully removed.");
601 "Overlay couldn't be removed.");
604 "No overlay for current map.");
620 "Usage: toggle_shout <player>.");
628 if (
pl->ob->contr->no_shout == 0) {
629 pl->ob->contr->no_shout = 1;
632 "You have been muzzled by the DM!");
642 pl->ob->contr->no_shout = 0;
644 "You are allowed to shout and chat again.");
646 "You remove %s's muzzle.",
659 if (strlen(
params) == 0) {
673 }
else if (strcmp(
params,
"cancel") == 0) {
677 LOG(
llevInfo,
"Server shutdown cancelled by %s.\n",
op->name);
683 }
else if (strncmp(
params,
"now", 3) == 0) {
689 LOG(
llevInfo,
"Server shutdown initiated by %s.\n",
op->name);
690 }
else if (strcmp(
params,
"idle") == 0) {
696 LOG(
llevInfo,
"Server idle shutdown scheduled by %s.\n",
op->name);
699 int minutes = atoi(
params);
701 if (minutes > 0 && minutes <= 720) {
704 "Server will shut down in %d minutes.", minutes);
707 LOG(
llevInfo,
"Server shutdown scheduled in %d minutes by %s.\n", minutes,
op->name);
711 "Please specify a reasonable time in minutes.");
730 "Go to what level?");
751 "Usage: freeze [ticks] <player>.");
761 "Usage: freeze [ticks] <player>.");
772 "You have been frozen by the DM!");
775 "You freeze %s for %d ticks",
776 pl->ob->name, ticks);
778 pl->ob->speed_left = -(
pl->ob->speed*ticks);
829 "Usage: arrest <player>.");
840 "Can't jail player, there is no map to hold them");
846 "Can't jail player, map loading issue or already in jail's position");
852 "You have been arrested.");
876 "Usage: summon <player>.");
887 "Can not find a free spot to place summoned player.");
898 "You are summoned.");
923 "Usage: teleport <player>.");
930 "No such player or ambiguous name.");
937 "Can not find a free spot to teleport to.");
947 if (!
op->contr->hidden)
949 "You see a portal open.");
951 "You teleport to %s",
982 int magic,
set_magic = 0, set_nrof = 0, gotquote, gotspace;
984 char *cp, *bp, *bp2, *bp3, *endline, cpy[
MAX_BUF];
993 "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1000 endline = bp+strlen(bp);
1002 if (sscanf(bp,
"%u ", &nrof)) {
1003 if ((bp = strchr(cpy,
' ')) == NULL) {
1005 "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1012 if (sscanf(bp,
"%d ", &magic)) {
1013 if ((bp = strchr(bp,
' ')) == NULL) {
1015 "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1020 LOG(
llevDebug,
"%s creates: (%d) (%d) %s\n",
op->name, nrof, magic, bp);
1022 if ((cp = strstr(bp,
" of ")) != NULL) {
1026 for (bp2 = bp; *bp2; bp2++) {
1036 "No such archetype.");
1041 char spell_name[
MAX_BUF], *fsp = NULL;
1054 fsp = strchr(spell_name,
' ');
1062 bp2 = cp+strlen(spell_name)+1;
1075 "No artifact list for type %d\n",
1079 auto i = std::find_if(items.cbegin(), items.cend(),
1080 [&] (
const auto art) { return !strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art); });
1081 art = i == items.cend() ? nullptr : *i;
1085 "No such artifact ([%d] of %s)",
1089 LOG(
llevDebug,
"%s creates: (%d) (%d) (%s) of (%s)\n",
op->name, set_nrof ? nrof : 0,
set_magic ? magic : 0, bp, cp);
1096 "Unable to find spell %s for object that needs it, or it is of wrong type",
1103 "Unable to find spell %s for object that needs it, or it is of wrong type",
1132 while (*bp2 && bp2 <= endline) {
1136 for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1150 }
else if (*bp3 ==
' ') {
1160 if (gotspace == 2 || gotquote == 2) {
1163 }
else if (*bp3 ==
'\0')
1166 if ((gotquote && gotquote != 2)
1167 || (gotspace != 2 && gotquote != 2)) {
1176 "Malformed create line: %s",
1185 "Unknown variable %s",
1190 tmp->name,
tmp->count, bp2);
1221 for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1223 object *prev = NULL, *head = NULL, *dup;
1225 for (atmp = at; atmp != NULL; atmp = atmp->
more) {
1241 dup->x =
op->x+dup->arch->clone.x;
1242 dup->y =
op->y+dup->arch->clone.y;
1253 object *
check = head;
1268 "Object too big to insert in map, or wrong position.");
1326 "Inventory of what object (nr)?");
1373 "Object is marked original");
1391 "Aggression turned OFF");
1396 "Aggression turned ON");
1420 if (sscanf(
params,
"%d", &i))
1427 "Patch what object (nr)?");
1433 "As insane as you are, I cannot allow you to possess yourself.");
1453 if (i == 1 || i == 6 || i == 8 || i == 9)
1454 victim->body_info[i] = 2;
1456 victim->body_info[i] = 1;
1474 const char *arg, *arg2;
1486 "Patch what values?");
1490 if ((arg2 = strchr(arg,
' ')))
1496 "Unknown variable %s",
1501 tmp->name,
tmp->count, arg, arg2);
1547 "Remove what object (nr)?");
1553 "Unable to remove a player!");
1562 "%s is already removed!",
1573 if (
tmp->speed != 0) {
1595 "Free what object (nr)?");
1606 "Warning: item was not removed, will do so now.");
1616 if (sscanf(
params,
"%s %[^\n]", account_name, newpw) != 2) {
1618 "Usage: accountpasswd ACCOUNT PASSWORD");
1626 "Updated account password.");
1630 "Invalid characters in new password.");
1634 "Invalid characters in new password.");
1638 "Error changing password.");
1654 object *skillob = NULL;
1662 "Usage: addexp player quantity [skill].");
1680 "Unable to find skill %s in %s",
1691 pl->ob->stats.exp += i;
1712 "Current speed is %d",
1720 "The speed is changed to %d.",
1754 "[Fixed]Statistics for %s:",
pl->ob->name);
1757 "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1758 pl->ob->stats.Str,
pl->ob->stats.hp,
pl->ob->stats.maxhp);
1761 "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1762 pl->ob->stats.Dex,
pl->ob->stats.sp,
pl->ob->stats.maxsp);
1765 "[fixed]Con : %-2d AC : %-4d WC : %d",
1766 pl->ob->stats.Con,
pl->ob->stats.ac,
pl->ob->stats.wc);
1769 "[fixed]Int : %-2d Damage : %d",
1770 pl->ob->stats.Int,
pl->ob->stats.dam);
1773 "[fixed]Wis : %-2d EXP : %" FMT64,
1774 pl->ob->stats.Wis,
pl->ob->stats.exp);
1777 "[fixed]Pow : %-2d Grace : %d",
1778 pl->ob->stats.Pow,
pl->ob->stats.grace);
1781 "[fixed]Cha : %-2d Food : %d",
1782 pl->ob->stats.Cha,
pl->ob->stats.food);
1795 char thing[20], thing2[20];
1803 || sscanf(
params,
"%s %s %d", thing, thing2, &iii) != 3
1804 || thing[0] ==
'\0') {
1810 if (thing2[0] ==
'\0') {
1812 "You can't change that.");
1818 "Illegal range of stat.\n");
1823 if (!strcmp(
pl->ob->name, thing)) {
1826 if (!strcmp(
"str", thing2))
1827 pl->ob->stats.Str = iii,
pl->orig_stats.Str = iii;
1828 if (!strcmp(
"dex", thing2))
1829 pl->ob->stats.Dex = iii,
pl->orig_stats.Dex = iii;
1830 if (!strcmp(
"con", thing2))
1831 pl->ob->stats.Con = iii,
pl->orig_stats.Con = iii;
1832 if (!strcmp(
"wis", thing2))
1833 pl->ob->stats.Wis = iii,
pl->orig_stats.Wis = iii;
1834 if (!strcmp(
"cha", thing2))
1835 pl->ob->stats.Cha = iii,
pl->orig_stats.Cha = iii;
1836 if (!strcmp(
"int", thing2))
1837 pl->ob->stats.Int = iii,
pl->orig_stats.Int = iii;
1838 if (!strcmp(
"pow", thing2))
1839 pl->ob->stats.Pow = iii,
pl->orig_stats.Pow = iii;
1841 "%s has been altered.",
1862 object *dummy = NULL, *
tmp = NULL;
1864 const char *
space, *confirmation = NULL;
1874 if (
space != NULL) {
1880 if (strcmp(
params,
".") == 0) {
1894 if (
m->unique && (
op->map ==
m)) {
1897 "Cannot reset a unique player map while on it. Use "
1898 "'reset full-reset %s' while standing somewhere else.",
1903 if (strncmp(
"full-reset", confirmation, strlen(
"full-reset"))) {
1913 if ((
op->contr &&
op->contr->transport) && (
op->map ==
m)) {
1915 "You need to disembark first.");
1921 sstring reset_group =
m->reset_group;
1922 m->reset_group = NULL;
1926 LOG(
llevError,
"Tried to swap out map which was not in memory.\n");
1927 m->reset_group = reset_group;
1936 if (strncmp(
m->path,
"/random/", 8) == 0) {
1946 "You cannot reset a random map when inside it.");
1947 m->reset_group = reset_group;
1976 "Reset failed, error code: %d.",
res);
1979 "Reset failed, couldn't swap map, the following players are on it:");
1981 if (
pl->ob->map ==
m &&
pl->ob !=
op) {
1989 "hmm, I don't see any other players on this map, something else is the problem.");
1990 m->reset_group = reset_group;
2026 if (confirmation == NULL) {
2029 "Use 'reset full-reset %s' to fully reset the map.",
params);
2049 if (
op->contr->hidden) {
2053 "The Dungeon Master is gone...");
2078 static int checkdm(
object *
op,
const char *pl_name,
const char *pl_passwd,
const char *pl_host) {
2081 char line_buf[160],
name[160], passwd[160], host[160];
2083 #ifdef RESTRICTIVE_DM
2084 *pl_name =
op->name ?
op->name :
"*";
2090 if ((dmfile = fopen(
buf,
"r")) == NULL) {
2095 while (fgets(line_buf, 160, dmfile) != NULL) {
2097 if (line_buf[0] ==
'#' || line_buf[0] ==
'\n')
2099 if (sscanf(line_buf,
"%[^:]:%[^:]:%s\n",
name, passwd, host) != 3) {
2100 LOG(
llevError,
"Warning - malformed dm file entry: %s\n", line_buf);
2101 }
else if ((!strcmp(
name,
"*") || (pl_name && !strcmp(pl_name,
name)))
2102 && (!strcmp(passwd,
"*") || !strcmp(passwd, pl_passwd))
2103 && (!strcmp(host,
"*") || !strcmp(host, pl_host))) {
2132 "You are already the Dungeon Master!");
2142 "Ok, you are the Dungeon Master!");
2154 "The Dungeon Master has arrived!");
2160 "Sorry Pal, I don't think so.");
2190 op->invisible += 100;
2193 "You turn invisible.");
2217 size_t spell_name_length;
2223 if (ar->clone.type !=
SPELL)
2226 if (strncmp(ar->name,
"spelldirect_", 12) == 0)
2229 if (strcmp(ar->clone.name, spell_name) != 0)
2233 if (!conflict_found) {
2236 "More than one archetype matches the spell name %s:",
2260 spell_name_length = strlen(spell_name);
2265 if (ar->clone.type !=
SPELL)
2268 if (strncmp(ar->name,
"spelldirect_", 12) == 0)
2271 if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2275 if (!conflict_found) {
2278 "More than one spell matches %s:",
2303 "The spell %s does not exist.",
2321 if (
op->contr == NULL || *
params ==
'\0') {
2323 "Which spell do you want to learn?");
2334 "You already know the spell %s.",
2379 if (
op->contr == NULL || *
params ==
'\0') {
2381 "Which spell do you want to forget?");
2386 if (
spell == NULL) {
2388 "You do not know the spell %s.",
2424 "Load which plugin?");
2428 snprintf(
buf,
sizeof(
buf), LIBDIR
"/plugins/%s",
params);
2433 "Plugin %s successfully loaded.",
2437 "Could not load plugin %s.",
2454 "Remove which plugin?");
2461 "Plugin %s successfully removed.",
2466 "Could not remove plugin %s.",
2533 "Item stack contents:");
2544 " %d : (lost item: %d)",
2559 op->contr->stack_position = 0;
2561 "Item stack cleared.");
2584 object *left, *right;
2587 int left_from, right_from;
2592 "Compare to what item?");
2604 "Compare what item?");
2609 "Item difference:");
2618 if (
op->contr->stack_position > 1) {
2622 "(Note: first item taken from undertop)");
2632 if (*diff ==
'\0') {
2648 object *left, *right, *inserted;
2649 int left_from, right_from;
2655 "Insert into what object?");
2667 "Insert what item?");
2678 if (
op->contr->stack_position > 1) {
2682 "(Note: item to insert into taken from undertop)");
2689 if (left == right) {
2691 "Can't insert an object into itself!");
2697 "Can't insert a player into something!");
2705 if (inserted != right)
2712 "Inserted %s in %s",
2727 int maps_used = 0, mapmem = 0, objects_used = 0,
x,
y;
2730 for (mp =
styles; mp != NULL; mp = mp->
next) {
2742 "[fixed]Style maps loaded: %d",
2745 "[fixed]Memory used, not");
2747 "[fixed]including objects: %d",
2750 "[fixed]Style objects: %d",
2753 "[fixed]Mem for objects: %lu",
2754 (
unsigned long)(objects_used*
sizeof(
object)));
2774 if (
op->contr->followed_player != NULL) {
2786 if (other ==
op->contr) {
2796 "You can only follow members in the same party.");
2807 if (
op->contr->followed_player)
2850 if (
op &&
op->below) {
2865 if (
op &&
op->above) {
static player * get_other_player_from_name(object *op, const char *name)
void command_overlay_reset(object *op, const char *params)
void command_possess(object *op, const char *params)
static void set_magic(int difficulty, object *op, int max_magic, int flags)
#define FREE_AND_CLEAR_STR_IF(xyz)
#define FREE_OBJ_NO_DESTROY_CALLBACK
uint8_t death_penalty_ratio
void set_abs_magic(object *op, int magic)
void command_overlay_save(object *op, const char *params)
#define NUM_BODY_LOCATIONS
#define MSG_TYPE_COMMAND_SUCCESS
void command_style_map_info(object *op, const char *params)
#define MSG_TYPE_ADMIN_PLAYER
void LOG(LogLevel logLevel, const char *format,...)
static void reset_faces_sent(struct socket_struct *socket)
void command_patch(object *op, const char *params)
#define QUERY_FLAG(xyz, p)
int plugins_remove_plugin(const char *id)
int plugins_init_plugin(const char *libfile)
void do_learn_spell(object *op, object *spell, int special_prayer)
void command_shutdown(object *op, const char *params)
mapstruct * has_been_loaded(const char *name)
void flush_old_maps(void)
void esrv_new_player(player *pl, uint32_t weight)
void command_speed(object *op, const char *params)
void esrv_send_inventory(object *pl, object *op)
static int do_wizard_dm(object *op, const char *params, int silent)
void command_learn_spell(object *op, const char *params)
StringBuffer * stringbuffer_new(void)
void object_set_enemy(object *op, object *enemy)
std::vector< artifact * > items
static void dm_stack_pop(player *pl)
#define FLAG_OBJ_ORIGINAL
void give_artifact_abilities(object *op, const object *artifact)
void command_arrest(object *op, const char *params)
void command_teleport(object *op, const char *params)
void command_mon_aggr(object *op, const char *params)
static void dm_stack_push(player *pl, tag_t item)
int64_t check_exp_adjust(const object *op, int64_t exp)
non standard information is not specified or uptime this means how long since the executable has been started A particular host may have been running a server for quite a long time
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
void command_purge_quest(object *op, const char *param)
void calc_perm_exp(object *op)
uint8_t spell_failure_effects
static void unhide(object *op)
void do_dump(object *who, object *what)
void object_copy(const object *src_ob, object *dest_ob)
uint8_t spell_encumbrance
void command_invisible(object *op, const char *params)
void fix_object(object *op)
void command_banish(object *op, const char *params)
void plugins_display_list(object *op)
void command_addexp(object *op, const char *params)
void command_listplugins(object *op, const char *params)
#define MSG_TYPE_COMMAND_ERROR
object * object_find_by_tag_global(tag_t i)
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
int set_variable(object *op, const char *buf)
void set_tick_duration(long t)
AssetsManager * getManager()
object * object_insert_in_ob(object *op, object *where)
const object * find_god(const char *name)
Plugin animator file specs[Config] name
int allow_denied_spells_writing
#define SAVE_MODE_OVERLAY
void command_learn_special_prayer(object *op, const char *params)
void command_remove(object *op, const char *params)
void map_remove_unique_files(const mapstruct *map)
#define MSG_TYPE_ADMIN_DM
#define MSG_TYPE_COMMAND_DEBUG
static event_registration m
void clear_los(player *pl)
char * stringbuffer_finish(StringBuffer *sb)
Crossfire Protocol most of the time after the actual code was already omit certain important and possibly make life miserable any new developer or curious player should be able to find most of the relevant information here If inconsistencies are found or this documentation proves to be consider the latest server side protocol code in the public source code repository as the authoritative reference Introduction If you were ever curious enough to telnet or netcat to a Crossfire chances are you were sorely disappointed While the protocol may seem to use plain text at it actually uses a mix of ASCII and binary data This handbook attempts to document various aspects of the Crossfire protocol As consult the README file to find out how to get in touch with helpful people via mailing and more History the communications plan was set to be a text based system It was up to the server and client to parse these messages and determine what to do These messages were assumed to be line per message At a reasonably early stage of Eric Anderson wrote a then the data itself you could send many data and after the other end could decode these commands This works fairly but I think the creation of numerous sub packets has some performance hit the eutl was not especially well so writing a client for a different platform became more Eric left to work on other products shortly after writing his which didn t really leave anyone with a full understanding of the socket code I have decided to remove the eutl dependency At least one advantage is that having this network related code directly in the client and server makes error handling a bit easier cleaner Packet Format the outside packet method the byte size for the size information is not included here Eutl originally used bytes for the size to bytes seems it makes a least some sense The actual data is something of the nature of the commands listed below It is a text followed by possible other data The remaining data can be binary it is up to the client and server to decode what it sent The commands as described below is just the data portion of the packet If writing a new remember that you must take into account the size of the packet There is no termination of other than knowing how long it should be For most everything that is sent is text This is more or less how things worked under except it packed the ints into bytes in a known order In some we handle ints as in they are sent as binary information How any command handles it is detailed below in the command description The S and C represent the direction of the we use MSB as well as any ints or shorts that get sent inside the packets All packets are defined to have at least one word of followed by a space
uint16_t set_friendly_fire
void object_free_drop_inventory(object *ob)
void object_update(object *op, int action)
void command_toggle_shout(object *op, const char *params)
uint32_t map_size(mapstruct *m)
void command_setgod(object *op, const char *params)
short freearr_y[SIZEOFFREE]
void command_create(object *op, const char *params)
void command_reset(object *op, const char *params)
static void do_wizard_hide(object *op, int silent_dm)
void query_name(const object *op, char *buf, size_t size)
void command_summon(object *op, const char *params)
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
#define MSG_TYPE_COMMAND_DM
void command_purge_quest_definitions(object *op, const char *param)
void object_dump(const object *op, StringBuffer *sb)
sstring add_string(const char *str)
void command_dm(object *op, const char *params)
int out_of_map(mapstruct *m, int x, int y)
void command_abil(object *op, const char *params)
object * lookup_spell_by_name(object *op, const char *spname)
void command_dumpbelow(object *op, const char *params)
void command_diff(object *op, const char *params)
void object_update_speed(object *op)
void command_inventory(object *op, const char *params)
void do_goto(object *op, const char *name, int x, int y)
void command_help(object *op, const char *params)
struct shutdown_s shutdown_state
void show_skills(object *op, const char *search)
void command_skills(object *op, const char *params)
object * object_create_arch(archetype *at)
with a maximum of six This is not so if you are wearing plate you receive no benefit Armour is additive with all the supplementry forms of which means that it lasts until the next semi permanent spell effect is cast upon the character spell
void player_lvl_adj(object *who, object *op)
void object_free(object *ob, int flags)
void command_dumpabove(object *op, const char *params)
Archetypes * archetypes()
void command_insert_into(object *op, const char *params)
#define FLAG_UNAGGRESSIVE
int become_follower(object *op, const object *new_god)
void command_goto(object *op, const char *params)
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
struct archetype * other_arch
object * find_skill_by_name(object *who, const char *name)
void command_kick(object *op, const char *params)
void command_loadtest(object *op, const char *params)
size_t strlcpy(char *dst, const char *src, size_t size)
object * object_new(void)
void create_overlay_pathname(const char *name, char *buf, size_t size)
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin path(SHARE/plugins). Console messages. ----------------- When Crossfire starts
void monster_check_apply_all(object *monster)
void command_hide(object *op, const char *params)
#define FREE_AND_CLEAR_STR(xyz)
void command_freeze(object *op, const char *params)
#define MSG_TYPE_COMMAND_FAILURE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
void command_forget_spell(object *op, const char *params)
void command_nowiz(object *op, const char *params)
int swap_map(mapstruct *map)
void command_loadplugin(object *op, const char *params)
archetype * find_archetype_by_object_name(const char *name)
object * get_jail_exit(object *op)
void each(std::function< void(T *)> op)
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
static object * get_spell_by_name(object *op, const char *spell_name)
uint8_t create_home_portals
bool can_follow(object *op, player *other)
int is_identifiable_type(const object *op)
void enter_exit(object *op, object *exit_ob)
object * object_find_by_name_global(const char *str)
object * check_spell_known(object *op, const char *name)
static object * find_object_both(const char *params)
const typedef char * sstring
void command_settings(object *op, const char *ignored)
void command_stats(object *op, const char *params)
void command_dump(object *op, const char *params)
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
void command_dmhide(object *op, const char *params)
void esrv_update_item(int flags, object *pl, object *op)
void command_unloadplugin(object *op, const char *params)
#define CLEAR_FLAG(xyz, p)
int player_arrest(object *who)
void command_follow(object *op, const char *params)
static object * get_dm_object(player *pl, const char **params, int *from)
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
player * find_player_partial_name(const char *plname)
int account_change_password(const char *account_name, const char *current_password, const char *new_password)
object * arch_to_object(archetype *at)
void object_give_identified_properties(object *op)
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various stats
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host)
#define MSG_TYPE_COMMAND_MAPS
void command_accountpasswd(object *op, const char *params)
struct treasurelist * randomitems
#define MSG_TYPE_COMMUNICATION_PARTY
void object_remove(object *op)
archetype * try_find_archetype(const char *name)
void inventory(object *op, object *inv)
void do_forget_spell(object *op, const char *spell)
static void command_kick2(object *op, const char *params)
void do_some_living(object *op)
Crossfire Protocol most of the time after the actual code was already omit certain important and possibly make life miserable any new developer or curious player should be able to find most of the relevant information here If inconsistencies are found or this documentation proves to be consider the latest server side protocol code in the public source code repository as the authoritative reference Introduction If you were ever curious enough to telnet or netcat to a Crossfire chances are you were sorely disappointed While the protocol may seem to use plain text at it actually uses a mix of ASCII and binary data This handbook attempts to document various aspects of the Crossfire protocol As consult the README file to find out how to get in touch with helpful people via mailing and more History the communications plan was set to be a text based system It was up to the server and client to parse these messages and determine what to do These messages were assumed to be line per message At a reasonably early stage of Eric Anderson wrote a then the data itself you could send many data and after the other end could decode these commands This works fairly but I think the creation of numerous sub packets has some performance hit the eutl was not especially well so writing a client for a different platform became more Eric left to work on other products shortly after writing his which didn t really leave anyone with a full understanding of the socket code I have decided to remove the eutl dependency At least one advantage is that having this network related code directly in the client and server makes error handling a bit easier cleaner Packet Format the outside packet method the byte size for the size information is not included here Eutl originally used bytes for the size to bytes seems it makes a least some sense The actual data is something of the nature of the commands listed below It is a text followed by possible other data The remaining data can be binary it is up to the client and server to decode what it sent The commands as described below is just the data portion of the packet If writing a new remember that you must take into account the size of the packet There is no termination of other than knowing how long it should be For now
uint8_t no_player_stealing
int save_map(mapstruct *m, int flag)
void command_stack_push(object *op, const char *params)
void assets_collect(const char *datadir, int what)
No space after the left no space before the right paren Comma right after the formal param
uint8_t permanent_exp_ratio
void command_free(object *op, const char *params)
#define MSG_TYPE_COMMUNICATION
void update_los(object *op)
short freearr_x[SIZEOFFREE]
void command_recollect(object *op, const char *params)
void command_stack_pop(object *op, const char *params)
uint8_t death_penalty_level
artifactlist * find_artifactlist(int type)
#define SAVE_ERROR_PLAYER
static object * dm_stack_peek(player *pl)
void events_execute_global_event(int eventcode,...)
void command_stack_clear(object *op, const char *params)
void command_stack_list(object *op, const char *params)