Crossfire Server, Trunk
dialog.cpp
Go to the documentation of this file.
1 
2 /*
3  * Crossfire -- cooperative multi-player graphical RPG and adventure game
4  *
5  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
6  * Copyright (c) 1992 Frank Tore Johansen
7  *
8  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
9  * welcome to redistribute it under certain conditions. For details, please
10  * see COPYING and LICENSE.
11  *
12  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
13  */
14 
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "global.h"
24 #include "define.h"
25 #include "object.h"
26 #include "dialog.h"
27 
32 void free_dialog_information(object *op) {
34  struct_dialog_reply *currep, *nextrep;
35 
37  return;
38 
40  if (!op->dialog_information)
41  return;
42 
43  current = op->dialog_information->all_messages;
44  while (current) {
45  next = current->next;
46  free(current->match);
47  free(current->message);
48  currep = current->replies;
49  while (currep) {
50  nextrep = currep->next;
51  free(currep->reply);
52  free(currep->message);
53  currep = nextrep;
54  }
55  free(current);
56  current = next;
57  }
58 
59  currep = op->dialog_information->all_replies;
60  while (currep) {
61  nextrep = currep->next;
62  free(currep->reply);
63  free(currep->message);
64  free(currep);
65  currep = nextrep;
66  }
67 
68  free(op->dialog_information);
69  op->dialog_information = NULL;
70 }
71 
79 static int matches(const char *exp, const char *text) {
80  char *pipe, *save = NULL, *msg;
81  int match = 0;
82 
83  if (exp[0] == '*')
84  return 1;
85 
86  msg = strdup(exp);
87 
88  pipe = strtok_r(msg, "|", &save);
89  while (pipe) {
90  if (re_cmp(text, pipe)) {
91  match = 1;
92  break;
93  }
94  pipe = strtok_r(NULL, "|", &save);
95  }
96 
97  free(msg);
98  return match;
99 }
100 
107 static void parse_dialog_information(object *op) {
108  struct_dialog_message *message = NULL, *last = NULL;
109  struct_dialog_reply *reply = NULL;
110  char *current, *save = NULL, *msg, *cp;
111  int len;
112  /* Used for constructing message with */
113  char *tmp = NULL;
114  size_t tmplen = 0;
115 
117  return;
119 
120  op->dialog_information = (struct_dialog_information *)calloc(1, sizeof(struct_dialog_information));
121  if (op->dialog_information == NULL)
123 
124  if (!op->msg)
125  return;
126 
127  msg = strdup(op->msg);
128  current = strtok_r(msg, "\n", &save);
129 
130  while (current) {
131  if (strncmp(current, "@match ", 7) == 0) {
132  if (message) {
133  message->message = tmp;
134  tmp = NULL;
135  tmplen = 0;
136  }
137 
138  message = (struct_dialog_message *)calloc(1, sizeof(struct_dialog_message));
139  if (last)
140  last->next = message;
141  else
142  op->dialog_information->all_messages = message;
143  last = message;
144 
145  message->match = strdup(current+7);
146  } else if ((strncmp(current, "@reply ", 7) == 0 && (len = 7)) || (strncmp(current, "@question ", 10) == 0 && (len = 10))) {
147  if (message) {
148  reply = (struct_dialog_reply *)calloc(1, sizeof(struct_dialog_reply));
149  reply->type = (len == 7 ? rt_reply : rt_question);
150  cp = strchr(current+len, ' ');
151  if (cp) {
152  *cp = '\0';
153  reply->reply = strdup(current+len);
154  reply->message = strdup(cp+1);
155  } else {
156  reply->reply = strdup(current+len);
157  reply->message = strdup(reply->reply);
158  LOG(llevDebug, "Warning: @reply/@question without message for %s!\n", op->name);
159  }
160  reply->next = message->replies;
161  message->replies = reply;
162 
163  reply = (struct_dialog_reply *)calloc(1, sizeof(struct_dialog_reply));
164  reply->reply = strdup(message->replies->reply);
165  reply->message = strdup(message->replies->message);
166  reply->type = message->replies->type;
167  reply->next = op->dialog_information->all_replies;
168  op->dialog_information->all_replies = reply;
169  } else
170  LOG(llevDebug, "Warning: @reply not in @match block for %s!\n", op->name);
171  } else if ((strncmp(current, "@identify", 9) == 0 && (len = 9))) {
172  if (message) {
173  message->identifies = true;
174  }
175  } else if (message) {
176  /* Needed to set initial \0 */
177  int wasnull = FALSE;
178  tmplen += strlen(current)+2;
179  if (!tmp)
180  wasnull = TRUE;
181  tmp = static_cast<char *>(realloc(tmp, tmplen*sizeof(char)));
182  if (!tmp)
184  if (wasnull)
185  tmp[0] = 0;
186  strncat(tmp, current, tmplen-strlen(tmp)-1);
187  strncat(tmp, "\n", tmplen-strlen(tmp)-1);
188  }
189  current = strtok_r(NULL, "\n", &save);
190  }
191 
192  if (message) {
193  if (!tmp)
194  message->message = strdup("");
195  else
196  message->message = tmp;
197  tmp = NULL;
198  tmplen = 0;
199  }
200 
201  free(msg);
202 }
203 
216 
217  for (*message = op->dialog_information->all_messages; *message; *message = (*message)->next) {
218  if (matches((*message)->match, text)) {
219  break;
220  }
221  }
222  if (!*message)
223  return 0;
224 
225  for (*reply = op->dialog_information->all_replies; *reply; *reply = (*reply)->next) {
226  if (strcmp((*reply)->reply, text) == 0)
227  break;
228  }
229 
230  return 1;
231 }
give.next
def next
Definition: give.py:44
player::next
player * next
Definition: player.h:106
global.h
struct_dialog_reply::next
struct struct_dialog_reply * next
Definition: dialog.h:20
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
FALSE
#define FALSE
Definition: compat.h:14
say.reply
string reply
Definition: say.py:77
Ice.tmp
int tmp
Definition: Ice.py:207
FLAG_DIALOG_PARSED
#define FLAG_DIALOG_PARSED
Definition: define.h:243
struct_dialog_reply::message
char * message
Definition: dialog.h:18
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
struct_dialog_reply
Definition: dialog.h:16
message
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your message
Definition: survival-guide.txt:34
push.match
bool match
Definition: push.py:61
struct_dialog_information
Definition: dialog.h:37
rt_reply
@ rt_reply
Definition: dialog.h:9
struct_dialog_reply::reply
char * reply
Definition: dialog.h:17
dialog.h
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:570
struct_dialog_message
Definition: dialog.h:26
get_dialog_message
int get_dialog_message(object *op, const char *text, struct_dialog_message **message, struct_dialog_reply **reply)
Definition: dialog.cpp:213
rt_question
@ rt_question
Definition: dialog.h:10
give.op
op
Definition: give.py:33
define.h
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
TRUE
#define TRUE
Definition: compat.h:11
replace.current
current
Definition: replace.py:64
text
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 text
Definition: protocol.txt:84
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
re_cmp
const char * re_cmp(const char *, const char *)
Definition: re-cmp.cpp:68
free_dialog_information
void free_dialog_information(object *op)
Definition: dialog.cpp:32
matches
static int matches(const char *exp, const char *text)
Definition: dialog.cpp:79
object.h
llevDebug
@ llevDebug
Definition: logger.h:13
parse_dialog_information
static void parse_dialog_information(object *op)
Definition: dialog.cpp:107