Crossfire Client, Trunk  R20223
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 
34 const char *const directions[] = {"stay", "north", "northeast",
35  "east", "southeast", "south",
36  "southwest", "west", "northwest"};
37 
41 void new_player(long tag, char *name, long weight, long face) {
42  Spell *spell, *spnext;
43 
44  cpl.ob->tag = tag;
45  cpl.ob->nrof = 1;
46  copy_name(cpl.ob->d_name, name);
47 
48  /* Right after player exit server will send this with empty name. */
49  if (strlen(name) != 0) {
50  keybindings_init(name);
51  }
52 
53  cpl.ob->weight = (float)weight / 1000;
54  cpl.ob->face = face;
55 
56  if (cpl.spelldata) {
57  for (spell = cpl.spelldata; spell; spell = spnext) {
58  spnext = spell->next;
59  free(spell);
60  }
61  cpl.spelldata = NULL;
62  }
63 }
64 
65 void look_at(int x, int y) {
66  cs_print_string(csocket.fd, "lookat %d %d", x, y);
67 }
68 
69 void client_send_apply(int tag) {
70  cs_print_string(csocket.fd, "apply %d", tag);
71 }
72 
73 void client_send_examine(int tag) {
74  cs_print_string(csocket.fd, "examine %d", tag);
75 }
76 
80 void client_send_move(int loc, int tag, int nrof) {
81  cs_print_string(csocket.fd, "move %d %d %d", loc, tag, nrof);
82 }
83 
84 /* Fire & Run code. The server handles repeating of these actions, so
85  * we only need to send a run or fire command for a particular direction
86  * once - we use the drun and dfire to keep track if we need to send
87  * the full command.
88  */
89 static int drun=-1, dfire=-1;
90 
91 void stop_fire() {
92  if (cpl.input_state != Playing) {
93  return;
94  }
95  dfire |= 0x100;
96 }
97 
98 void clear_fire() {
99  if (dfire != -1) {
100  send_command("fire_stop", -1, SC_FIRERUN);
101  dfire = -1;
102  }
103 }
104 
105 void clear_run() {
106  if (drun != -1) {
107  send_command("run_stop", -1, SC_FIRERUN);
108  drun = -1;
109  }
110 }
111 
112 void fire_dir(int dir) {
113  if (cpl.input_state != Playing) {
114  return;
115  }
116  if (dir != dfire) {
117  char buf[MAX_BUF];
118  snprintf(buf, sizeof(buf), "fire %d", dir);
119  if (send_command(buf, cpl.count, SC_NORMAL)) {
120  dfire = dir;
121  cpl.count = 0;
122  }
123  } else {
124  dfire &= 0xff; /* Mark it so that we need a stop_fire */
125  }
126 }
127 
128 void stop_run() {
129  send_command("run_stop", -1, SC_FIRERUN);
130  drun |= 0x100;
131 }
132 
133 void run_dir(int dir) {
134  if (dir != drun) {
135  char buf[MAX_BUF];
136  snprintf(buf, sizeof(buf), "run %d", dir);
137  if (send_command(buf, -1, SC_NORMAL)) {
138  drun = dir;
139  }
140  } else {
141  drun &= 0xff;
142  }
143 }
144 
145 /* This should be used for all 'command' processing. Other functions should
146  * call this so that proper windowing will be done.
147  * command is the text command, repeat is a count value, or -1 if none
148  * is desired and we don't want to reset the current count.
149  * must_send means we must send this command no matter what (ie, it is
150  * an administrative type of command like fire_stop, and failure to send
151  * it will cause definate problems
152  * return 1 if command was sent, 0 if not sent.
153  */
154 int send_command(const char *command, int repeat, int must_send) {
155  static char last_command[MAX_BUF]="";
156 
157  script_monitor(command,repeat,must_send);
158  if (cpl.input_state==Reply_One) {
159  LOG(LOG_ERROR,"common::send_command","Wont send command '%s' - since in reply mode!",
160  command);
161  cpl.count=0;
162  return 0;
163  }
164 
165  /* Does the server understand 'ncom'? If so, special code */
166  if (csocket.cs_version >= 1021) {
168 
169  if (commdiff<0) {
170  commdiff +=256;
171  }
172 
173  /* if too many unanswered commands, not a must send, and command is
174  * the same, drop it
175  */
176  if (commdiff>use_config[CONFIG_CWINDOW] && !must_send && !strcmp(command, last_command)) {
177  if (repeat!=-1) {
178  cpl.count=0;
179  }
180  return 0;
181 #if 0 /* Obnoxious warning message we don't need */
182  fprintf(stderr,"Wont send command %s - window oversized %d %d\n",
184 #endif
185  } else {
186  SockList sl;
187  guint8 buf[MAX_BUF];
188 
189  /* Don't want to copy in administrative commands */
190  if (!must_send) {
191  strcpy(last_command, command);
192  }
194  csocket.command_sent &= 0xff; /* max out at 255 */
195 
196  SockList_Init(&sl, buf);
197  SockList_AddString(&sl, "ncom ");
199  SockList_AddInt(&sl, repeat);
200  SockList_AddString(&sl, command);
201  SockList_Send(&sl, csocket.fd);
202  }
203  } else {
204  cs_print_string(csocket.fd, "command %d %s", repeat,command);
205  }
206  if (repeat!=-1) {
207  cpl.count=0;
208  }
209  return 1;
210 }
211 
212 void CompleteCmd(unsigned char *data, int len) {
213  if (len !=6) {
214  LOG(LOG_ERROR,"common::CompleteCmd","Invalid length %d - ignoring", len);
215  return;
216  }
220 }
221 
222 /* This does special processing on the 'take' command. If the
223  * player has a container open, we want to specifiy what object
224  * to move from that since we've sorted it. command is
225  * the command as tped, cpnext is any optional params.
226  */
227 void command_take(const char *command, const char *cpnext) {
228  /* If the player has specified optional data, or the player
229  * does not have a container open, just issue the command
230  * as normal
231  */
232  if (cpnext || cpl.container == NULL) {
233  send_command(command, cpl.count, 0);
234  } else {
235  if (cpl.container->inv == NULL)
237  "There is nothing in the container to move");
238  else
239  cs_print_string(csocket.fd,"move %d %d %d", cpl.ob->tag,
241  }
242 }
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:127
void SockList_AddShort(SockList *sl, guint16 data)
Definition: newsocket.c:80
void command_take(const char *command, const char *cpnext)
Definition: player.c:227
gint16 use_config[CONFIG_NUMS]
Definition: init.c:40
void run_dir(int dir)
Definition: player.c:133
short GetShort_String(const unsigned char *data)
Definition: newsocket.c:188
item * ob
Player object.
Definition: client.h:335
int SockList_Send(SockList *sl, int fd)
Send data from a socklist to the socket.
Definition: newsocket.c:131
ClientSocket csocket
Definition: client.c:70
#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:476
void LOG(LogLevel level, const char *origin, const char *format,...)
Log messages of a certain importance to stderr.
Definition: misc.c:112
void client_send_apply(int tag)
Definition: player.c:69
void look_at(int x, int y)
Definition: player.c:65
#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:311
void SockList_AddInt(SockList *sl, guint32 data)
Definition: newsocket.c:96
int send_command(const char *command, int repeat, int must_send)
Definition: player.c:154
void clear_fire()
Definition: player.c:98
char d_name[NAME_LEN]
Definition: item.h:55
Client_Player cpl
Player object.
Definition: client.c:69
item * container
open container
Definition: client.h:338
void client_send_move(int loc, int tag, int nrof)
Request to move 'nrof' objects with 'tag' to 'loc'.
Definition: player.c:80
#define CONFIG_CWINDOW
Definition: client.h:187
void SockList_AddString(SockList *sl, const char *str)
Definition: newsocket.c:114
#define MAX_BUF
Definition: client.h:38
void new_player(long tag, char *name, long weight, long face)
Initialize player object using information from the server.
Definition: player.c:41
guint32 count
Repeat count on command.
Definition: client.h:358
struct Spell_struct * next
Definition: client.h:294
Warning that something definitely didn't work.
Definition: client.h:443
void stop_fire()
Definition: player.c:91
static int drun
Definition: player.c:89
Spell * spelldata
List of spells known.
Definition: client.h:349
#define SC_NORMAL
Definition: client.h:91
static int dfire
Definition: player.c:89
#define SC_FIRERUN
Definition: client.h:92
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:931
void SockList_Init(SockList *sl, guint8 *buf)
Definition: newsocket.c:48
int command_sent
Definition: client.h:122
void client_send_examine(int tag)
Definition: player.c:73
Input_State input_state
What the input state is.
Definition: client.h:340
int command_received
These are used for the newer 'windowing' method of commands - number of last command sent...
Definition: client.h:122
void CompleteCmd(unsigned char *data, int len)
Definition: player.c:212
Includes various dependencies header files needed by most everything.
char * name
Definition: image.c:39
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
void clear_run()
Definition: player.c:105
void stop_run()
Definition: player.c:128
int GetInt_String(const unsigned char *data)
The reverse of SockList_AddInt, but on strings instead.
Definition: newsocket.c:158
const char *const directions[]
Array for direction strings for each numeric direction.
Definition: player.c:34
void fire_dir(int dir)
Definition: player.c:112
void script_monitor(const char *command, int repeat, int must_send)
Definition: script.c:915
int cs_version
Definition: client.h:120
void keybindings_init(const char *character_name)
Reads in the keybindings, and initializes special values.
Definition: keys.c:534