Crossfire Client, Branches  R11627
player.c
Go to the documentation of this file.
1 const char * const rcsid_common_player_c =
2  "$Id: player.c 9201 2008-06-01 17:32:45Z anmaster $";
3 /*
4  Crossfire client, a client program for the crossfire program.
5 
6  Copyright (C) 2001 Mark Wedel & Crossfire Development Team
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22  The author can be reached via e-mail to crossfire-devel@real-time.com
23 */
24 
25 
26 #include <client.h>
27 #include <external.h>
28 #include <script.h>
29 
30 /* This file handles various player related functions. This includes
31  * both things that operate on the player item, cpl structure, or
32  * various commands that the player issues.
33  *
34  * This file does most of the handling of commands from the client to
35  * server (see commands.c for server->client)
36  *
37  * does most of the work for sending messages to the server
38  * Again, most of these appear self explanatory. Most send a bunch of
39  * commands like apply, examine, fire, run, etc. This looks like it
40  * was done by Mark to remove the old keypress stupidity I used.
41  */
42 
43 /* This translates the numeric direction id's into the actual direction
44  * commands. This lets us send the actual command (ie, 'north'), which
45  * makes handling on the server side easier.
46  */
47 
48 const char *const directions[9] = {"stay", "north", "northeast", "east", "southeast",
49  "south","southwest", "west", "northwest"};
50 
51 
52 /*
53  * Initialiazes player item, information is received from server
54  */
55 void new_player (long tag, char *name, long weight, long face)
56 {
57  Spell *spell, *spnext;
58 
59  cpl.ob->tag = tag;
60  cpl.ob->nrof = 1;
61  copy_name (cpl.ob->d_name, name);
62  cpl.ob->weight = (float) weight / 1000;
63  cpl.ob->face = face;
64 
65  if (cpl.spelldata) {
66  for (spell = cpl.spelldata; spell; spell = spnext) {
67  spnext = spell->next;
68  free(spell);
69  }
70  cpl.spelldata = NULL;
71  }
72 
73 }
74 
75 void look_at(int x, int y)
76 {
77  cs_print_string(csocket.fd, "lookat %d %d", x, y);
78 }
79 
80 void client_send_apply (int tag)
81 {
82  cs_print_string(csocket.fd, "apply %d", tag);
83 }
84 
85 void client_send_examine (int tag)
86 {
87  cs_print_string(csocket.fd, "examine %d", tag);
88 
89 }
90 
91 /* Requests nrof objects of tag get moved to loc. */
92 void client_send_move (int loc, int tag, int nrof)
93 {
94  cs_print_string(csocket.fd, "move %d %d %d", loc, tag, nrof);
95 }
96 
97 
98 
99 void move_player(int dir) {
100  /* Should we perhaps use the real repeat count here? */
101  send_command(directions[dir], -1, SC_NORMAL);
102 }
103 
104 
105 /* Fire & Run code. The server handles repeating of these actions, so
106  * we only need to send a run or fire command for a particular direction
107  * once - we use the drun and dfire to keep track if we need to send
108  * the full command.
109  */
110 static int drun=-1, dfire=-1;
111 
112 /* Fires in a specified direction. Note that direction 0 is a valid
113  * case - the fire is centered on the player.
114  */
115 
116 void stop_fire(void)
117 {
118  if (cpl.input_state != Playing) return;
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  char buf[MAX_BUF];
153 
154  if (cpl.input_state != Playing) return;
155  if (dir!= dfire) {
156  snprintf(buf, sizeof(buf), "fire %d", dir);
157  if (send_command(buf, cpl.count, SC_NORMAL)) {
158  dfire=dir;
159  cpl.count=0;
160  }
161  } else {
162  dfire &= 0xff; /* Mark it so that we need a stop_fire */
163  }
164 }
165 
166 void stop_run(void)
167 {
168  send_command("run_stop", -1, SC_FIRERUN);
169  drun |= 0x100;
170 }
171 
172 void run_dir(int dir) {
173  char buf[MAX_BUF];
174 
175  if (dir!=drun) {
176  snprintf(buf, sizeof(buf), "run %d", dir);
177  if (send_command(buf, -1, SC_NORMAL))
178  drun=dir;
179  } else {
180  drun &= 0xff;
181  }
182 }
183 
184 
185 /* This should be used for all 'command' processing. Other functions should
186  * call this so that proper windowing will be done.
187  * command is the text command, repeat is a count value, or -1 if none
188  * is desired and we don't want to reset the current count.
189  * must_send means we must send this command no matter what (ie, it is
190  * an administrative type of command like fire_stop, and failure to send
191  * it will cause definate problems
192  * return 1 if command was sent, 0 if not sent.
193  */
194 
195 int send_command(const char *command, int repeat, int must_send) {
196  static char last_command[MAX_BUF]="";
197 
198  script_monitor(command,repeat,must_send);
199  if (cpl.input_state==Reply_One) {
200  LOG(LOG_ERROR,"common::send_command","Wont send command '%s' - since in reply mode!",
201  command);
202  cpl.count=0;
203  return 0;
204  }
205 
206  /* Does the server understand 'ncom'? If so, special code */
207  if (csocket.cs_version >= 1021) {
209 
210  if (commdiff<0) commdiff +=256;
211 
212  /* if too many unanswered commands, not a must send, and command is
213  * the same, drop it
214  */
215  if (commdiff>use_config[CONFIG_CWINDOW] && !must_send && !strcmp(command, last_command)) {
216  if (repeat!=-1) cpl.count=0;
217  return 0;
218 #if 0 /* Obnoxious warning message we don't need */
219  fprintf(stderr,"Wont send command %s - window oversized %d %d\n",
221 #endif
222  }
223  else {
224  SockList sl;
225  uint8 buf[MAX_BUF];
226 
227  /* Don't want to copy in administrative commands */
228  if (!must_send) strcpy(last_command, command);
230  csocket.command_sent &= 0xff; /* max out at 255 */
231 
232  SockList_Init(&sl, buf);
233  SockList_AddString(&sl, "ncom ");
235  SockList_AddInt(&sl, repeat);
236  SockList_AddString(&sl, command);
237  SockList_Send(&sl, csocket.fd);
238  }
239  } else {
240  cs_print_string(csocket.fd, "command %d %s", repeat,command);
241  }
242  if (repeat!=-1) cpl.count=0;
243  return 1;
244 }
245 
246 void CompleteCmd(unsigned char *data, int len)
247 {
248  if (len !=6) {
249  LOG(LOG_ERROR,"common::CompleteCmd","Invalid length %d - ignoring", len);
250  return;
251  }
255 }
256 
257 
258 
259 /* This does special processing on the 'take' command. If the
260  * player has a container open, we want to specifiy what object
261  * to move from that since we've sorted it. command is
262  * the command as tped, cpnext is any optional params.
263  */
264 void command_take (const char *command, const char *cpnext)
265 {
266  /* If the player has specified optional data, or the player
267  * does not have a container open, just issue the command
268  * as normal
269  */
270  if (cpnext || cpl.container == NULL)
271  send_command(command, cpl.count, 0);
272  else {
273  if (cpl.container->inv == NULL)
274  draw_info("There is nothing in the container to move", NDI_BLACK);
275  else
276  cs_print_string(csocket.fd,"move %d %d %d", cpl.ob->tag,
278  }
279 }
float weight
Definition: item.h:56
void SockList_Init(SockList *sl, uint8 *buf)
Definition: newsocket.c:91
#define copy_name(t, f)
Definition: item.h:38
uint32 count
Definition: client.h:295
int command_time
Definition: client.h:105
void move_player(int dir)
Definition: player.c:99
void command_take(const char *command, const char *cpnext)
Definition: player.c:264
void clear_fire_run(void)
Definition: player.c:122
const char *const directions[9]
Definition: player.c:48
void stop_fire(void)
Definition: player.c:116
void clear_fire(void)
Definition: player.c:134
void run_dir(int dir)
Definition: player.c:172
short GetShort_String(const unsigned char *data)
Definition: newsocket.c:162
item * ob
Definition: client.h:272
int SockList_Send(SockList *sl, int fd)
Definition: newsocket.c:127
ClientSocket csocket
Definition: client.c:78
void clear_run(void)
Definition: player.c:142
void script_sync(int commdiff)
Definition: script.c:488
void SockList_AddInt(SockList *sl, uint32 data)
Definition: newsocket.c:109
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:178
void client_send_apply(int tag)
Definition: player.c:80
#define CONFIG_CWINDOW
Definition: client.h:155
void look_at(int x, int y)
Definition: player.c:75
int cs_print_string(int fd, const char *str,...)
Definition: newsocket.c:259
int send_command(const char *command, int repeat, int must_send)
Definition: player.c:195
sint16 use_config[CONFIG_NUMS]
Definition: init.c:50
char d_name[NAME_LEN]
Definition: item.h:50
Client_Player cpl
Definition: client.c:77
item * container
Definition: client.h:275
sint32 tag
Definition: item.h:54
void client_send_move(int loc, int tag, int nrof)
Definition: player.c:92
char * name
Definition: image.c:61
int fd
Definition: client.h:97
void SockList_AddString(SockList *sl, const char *str)
Definition: newsocket.c:117
void new_player(long tag, char *name, long weight, long face)
Definition: player.c:55
struct Spell_struct * next
Definition: client.h:249
#define MAX_BUF
Definition: client-types.h:128
static int drun
Definition: player.c:110
Spell * spelldata
Definition: client.h:286
void stop_run(void)
Definition: player.c:166
static int dfire
Definition: player.c:110
uint32 nrof
Definition: item.h:55
void SockList_AddShort(SockList *sl, uint16 data)
Definition: newsocket.c:102
int command_sent
Definition: client.h:103
void client_send_examine(int tag)
Definition: player.c:85
Input_State input_state
Definition: client.h:277
#define SC_NORMAL
Definition: client.h:67
const char *const rcsid_common_player_c
Definition: player.c:1
int command_received
Definition: client.h:103
void draw_info(const char *str, int color)
Definition: gx11.c:1773
void CompleteCmd(unsigned char *data, int len)
Definition: player.c:246
unsigned char uint8
Definition: client-types.h:81
#define NDI_BLACK
Definition: newclient.h:201
struct item_struct * inv
Definition: item.h:49
int GetInt_String(const unsigned char *data)
Definition: newsocket.c:143
sint16 face
Definition: item.h:57
void fire_dir(int dir)
Definition: player.c:151
void script_monitor(const char *command, int repeat, int must_send)
Definition: script.c:854
#define SC_FIRERUN
Definition: client.h:68
int cs_version
Definition: client.h:99