Crossfire Client, Trunk  R19545
player.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
29 #include <client.h>
30 #include <external.h>
31 #include <script.h>
32 
33 /* This translates the numeric direction id's into the actual direction
34  * commands. This lets us send the actual command (ie, 'north'), which
35  * makes handling on the server side easier.
36  */
37 
38 const char *const directions[9] = {"stay", "north", "northeast", "east", "southeast",
39  "south","southwest", "west", "northwest"
40  };
41 
42 
43 /*
44  * Initialiazes player item, information is received from server
45  */
46 void new_player (long tag, char *name, long weight, long face)
47 {
48  Spell *spell, *spnext;
49 
50  cpl.ob->tag = tag;
51  cpl.ob->nrof = 1;
52  copy_name (cpl.ob->d_name, name);
53 
54  /* Right after player exit server will send this with empty name. */
55  if (strlen(name) != 0) {
56  keybindings_init(name);
57  }
58 
59  cpl.ob->weight = (float) weight / 1000;
60  cpl.ob->face = face;
61 
62  if (cpl.spelldata) {
63  for (spell = cpl.spelldata; spell; spell = spnext) {
64  spnext = spell->next;
65  free(spell);
66  }
67  cpl.spelldata = NULL;
68  }
69 
70 }
71 
72 void look_at(int x, int y)
73 {
74  cs_print_string(csocket.fd, "lookat %d %d", x, y);
75 }
76 
77 void client_send_apply (int tag)
78 {
79  cs_print_string(csocket.fd, "apply %d", tag);
80 }
81 
82 void client_send_examine (int tag)
83 {
84  cs_print_string(csocket.fd, "examine %d", tag);
85 
86 }
87 
88 /* Requests nrof objects of tag get moved to loc. */
89 void client_send_move (int loc, int tag, int nrof)
90 {
91  cs_print_string(csocket.fd, "move %d %d %d", loc, tag, nrof);
92 }
93 
94 
95 
96 void move_player(int dir)
97 {
98  /* Should we perhaps use the real repeat count here? */
100 }
101 
102 
103 /* Fire & Run code. The server handles repeating of these actions, so
104  * we only need to send a run or fire command for a particular direction
105  * once - we use the drun and dfire to keep track if we need to send
106  * the full command.
107  */
108 static int drun=-1, dfire=-1;
109 
110 /* Fires in a specified direction. Note that direction 0 is a valid
111  * case - the fire is centered on the player.
112  */
113 
114 void stop_fire(void)
115 {
116  if (cpl.input_state != Playing) {
117  return;
118  }
119  dfire |= 0x100;
120 }
121 
122 void clear_fire_run(void)
123 {
124  if ((dfire!=-1) && (dfire & 0x100)) {
125  send_command("fire_stop", -1, SC_FIRERUN);
126  dfire=-1;
127  }
128  if ((drun!=-1) && (drun & 0x100)) {
129  send_command("run_stop", -1, SC_FIRERUN);
130  drun=-1;
131  }
132 }
133 
134 void clear_fire(void)
135 {
136  if (dfire!=-1) {
137  send_command("fire_stop", -1, SC_FIRERUN);
138  dfire=-1;
139  }
140 }
141 
142 void clear_run(void)
143 {
144  if (drun!=-1) {
145  send_command("run_stop", -1, SC_FIRERUN);
146  drun=-1;
147  }
148 }
149 
150 
151 void fire_dir(int dir)
152 {
153  char buf[MAX_BUF];
154 
155  if (cpl.input_state != Playing) {
156  return;
157  }
158  if (dir!= dfire) {
159  snprintf(buf, sizeof(buf), "fire %d", dir);
160  if (send_command(buf, cpl.count, SC_NORMAL)) {
161  dfire=dir;
162  cpl.count=0;
163  }
164  } else {
165  dfire &= 0xff; /* Mark it so that we need a stop_fire */
166  }
167 }
168 
169 void stop_run(void)
170 {
171  send_command("run_stop", -1, SC_FIRERUN);
172  drun |= 0x100;
173 }
174 
175 void run_dir(int dir)
176 {
177  char buf[MAX_BUF];
178 
179  if (dir!=drun) {
180  snprintf(buf, sizeof(buf), "run %d", dir);
181  if (send_command(buf, -1, SC_NORMAL)) {
182  drun=dir;
183  }
184  } else {
185  drun &= 0xff;
186  }
187 }
188 
189 
190 /* This should be used for all 'command' processing. Other functions should
191  * call this so that proper windowing will be done.
192  * command is the text command, repeat is a count value, or -1 if none
193  * is desired and we don't want to reset the current count.
194  * must_send means we must send this command no matter what (ie, it is
195  * an administrative type of command like fire_stop, and failure to send
196  * it will cause definate problems
197  * return 1 if command was sent, 0 if not sent.
198  */
199 
200 int send_command(const char *command, int repeat, int must_send)
201 {
202  static char last_command[MAX_BUF]="";
203 
204  script_monitor(command,repeat,must_send);
205  if (cpl.input_state==Reply_One) {
206  LOG(LOG_ERROR,"common::send_command","Wont send command '%s' - since in reply mode!",
207  command);
208  cpl.count=0;
209  return 0;
210  }
211 
212  /* Does the server understand 'ncom'? If so, special code */
213  if (csocket.cs_version >= 1021) {
215 
216  if (commdiff<0) {
217  commdiff +=256;
218  }
219 
220  /* if too many unanswered commands, not a must send, and command is
221  * the same, drop it
222  */
223  if (commdiff>use_config[CONFIG_CWINDOW] && !must_send && !strcmp(command, last_command)) {
224  if (repeat!=-1) {
225  cpl.count=0;
226  }
227  return 0;
228 #if 0 /* Obnoxious warning message we don't need */
229  fprintf(stderr,"Wont send command %s - window oversized %d %d\n",
231 #endif
232  } else {
233  SockList sl;
234  guint8 buf[MAX_BUF];
235 
236  /* Don't want to copy in administrative commands */
237  if (!must_send) {
238  strcpy(last_command, command);
239  }
241  csocket.command_sent &= 0xff; /* max out at 255 */
242 
243  SockList_Init(&sl, buf);
244  SockList_AddString(&sl, "ncom ");
246  SockList_AddInt(&sl, repeat);
247  SockList_AddString(&sl, command);
248  SockList_Send(&sl, csocket.fd);
249  }
250  } else {
251  cs_print_string(csocket.fd, "command %d %s", repeat,command);
252  }
253  if (repeat!=-1) {
254  cpl.count=0;
255  }
256  return 1;
257 }
258 
259 void CompleteCmd(unsigned char *data, int len)
260 {
261  if (len !=6) {
262  LOG(LOG_ERROR,"common::CompleteCmd","Invalid length %d - ignoring", len);
263  return;
264  }
268 }
269 
270 
271 
272 /* This does special processing on the 'take' command. If the
273  * player has a container open, we want to specifiy what object
274  * to move from that since we've sorted it. command is
275  * the command as tped, cpnext is any optional params.
276  */
277 void command_take (const char *command, const char *cpnext)
278 {
279  /* If the player has specified optional data, or the player
280  * does not have a container open, just issue the command
281  * as normal
282  */
283  if (cpnext || cpl.container == NULL) {
284  send_command(command, cpl.count, 0);
285  } else {
286  if (cpl.container->inv == NULL)
288  "There is nothing in the container to move");
289  else
290  cs_print_string(csocket.fd,"move %d %d %d", cpl.ob->tag,
292  }
293 }
float weight
Definition: item.h:61
#define copy_name(t, f)
Definition: item.h:43
int command_time
Time (in ms) players commands currently take to execute.
Definition: client.h:100
void SockList_AddShort(SockList *sl, guint16 data)
Definition: newsocket.c:95
void move_player(int dir)
Definition: player.c:96
void command_take(const char *command, const char *cpnext)
Definition: player.c:277
gint16 use_config[CONFIG_NUMS]
Definition: init.c:39
void clear_fire_run(void)
Definition: player.c:122
const char *const directions[9]
Definition: player.c:38
void stop_fire(void)
Definition: player.c:114
void clear_fire(void)
Definition: player.c:134
void run_dir(int dir)
Definition: player.c:175
short GetShort_String(const unsigned char *data)
Definition: newsocket.c:190
item * ob
Player object.
Definition: client.h:309
int SockList_Send(SockList *sl, int fd)
Send data from a socklist to the socket.
Definition: newsocket.c:136
ClientSocket csocket
Definition: client.c:71
void clear_run(void)
Definition: player.c:142
#define MSG_TYPE_CLIENT
Client originated Messages.
Definition: newclient.h:420
Contains external calls that the common area makes callbacks to.
#define NDI_BLACK
Definition: newclient.h:249
gint32 tag
Definition: item.h:59
guint32 nrof
Definition: item.h:60
void script_sync(int commdiff)
Definition: script.c:480
void LOG(LogLevel level, const char *origin, const char *format,...)
Log messages of a certain importance to stderr.
Definition: misc.c:111
void client_send_apply(int tag)
Definition: player.c:77
void look_at(int x, int y)
Definition: player.c:72
#define MSG_TYPE_CLIENT_NOTICE
Non-critical note to player.
Definition: newclient.h:689
int cs_print_string(int fd, const char *str,...)
Send a printf-formatted packet to the socket.
Definition: newsocket.c:313
void SockList_AddInt(SockList *sl, guint32 data)
Definition: newsocket.c:106
int send_command(const char *command, int repeat, int must_send)
Definition: player.c:200
char d_name[NAME_LEN]
Definition: item.h:55
Client_Player cpl
Player object.
Definition: client.c:70
item * container
open container
Definition: client.h:312
void client_send_move(int loc, int tag, int nrof)
Definition: player.c:89
int fd
Definition: client.h:91
#define CONFIG_CWINDOW
Definition: client.h:161
void SockList_AddString(SockList *sl, const char *str)
Definition: newsocket.c:119
void new_player(long tag, char *name, long weight, long face)
Definition: player.c:46
guint32 count
Repeat count on command.
Definition: client.h:332
struct Spell_struct * next
Definition: client.h:268
#define MAX_BUF
Definition: client-types.h:43
static int drun
Definition: player.c:108
Spell * spelldata
List of spells known.
Definition: client.h:323
void stop_run(void)
Definition: player.c:169
#define SC_NORMAL
Definition: client.h:57
static int dfire
Definition: player.c:108
#define SC_FIRERUN
Definition: client.h:58
void draw_ext_info(int orig_color, int type, int subtype, const char *message)
A message processor that accepts messages along with meta information color and type.
Definition: info.c:934
void SockList_Init(SockList *sl, guint8 *buf)
Definition: newsocket.c:74
int command_sent
Definition: client.h:95
void client_send_examine(int tag)
Definition: player.c:82
Input_State input_state
What the input state is.
Definition: client.h:314
int command_received
These are used for the newer 'windowing' method of commands - number of last command sent...
Definition: client.h:95
void CompleteCmd(unsigned char *data, int len)
Definition: player.c:259
Includes various dependencies header files needed by most everything.
char * name
Definition: image.c:56
gint16 face
Definition: item.h:62
struct item_struct * inv
Definition: item.h:54
Contains the base information we use to make up a packet we want to send.
Definition: newclient.h:705
int GetInt_String(const unsigned char *data)
The reverse of SockList_AddInt, but on strings instead.
Definition: newsocket.c:160
void fire_dir(int dir)
Definition: player.c:151
void script_monitor(const char *command, int repeat, int must_send)
Definition: script.c:919
int cs_version
Definition: client.h:93
void keybindings_init(const char *character_name)
Reads in the keybindings, and initializes special values.
Definition: keys.c:545