ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/socket/item.C
(Generate patch)

Comparing deliantra/server/socket/item.C (file contents):
Revision 1.4 by root, Sun Sep 3 00:18:43 2006 UTC vs.
Revision 1.24 by root, Sat Dec 16 22:14:42 2006 UTC

1
2/*
3 * static char *rcsid_item_c =
4 * "$Id: item.C,v 1.4 2006/09/03 00:18:43 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 The author can be reached via e-mail to crossfire-devel@real-time.com 21 The author can be reached via e-mail to <crossfire@schmorp.de>
28*/ 22*/
29 23
30/** 24/**
31 * \file 25 * \file
32 * Client/server logic. 26 * Client/server logic.
36 * This containes item logic for client/server. It doesn't contain 30 * This containes item logic for client/server. It doesn't contain
37 * the actual commands that send the data, but does contain 31 * the actual commands that send the data, but does contain
38 * the logic for what items should be sent. 32 * the logic for what items should be sent.
39 */ 33 */
40 34
41
42#include <global.h> 35#include <global.h>
43#include <object.h> /* LOOK_OBJ */ 36#include <object.h> /* LOOK_OBJ */
44#include <newclient.h>
45#include <newserver.h>
46#include <sproto.h> 37#include <sproto.h>
47 38
48/** This is the maximum number of bytes we expect any one item to take up */ 39/** This is the maximum number of bytes we expect any one item to take up */
49#define MAXITEMLEN 300 40#define MAXITEMLEN 300
50 41
53 * Functions related to sending object data to the client. 44 * Functions related to sending object data to the client.
54 * 45 *
55 ******************************************************************************/ 46 ******************************************************************************/
56 47
57/** 48/**
58 * Adds string to socklist.
59 *
60 * This is a simple function that we use a lot here. It basically
61 * adds the specified buffer into the socklist, but prepends a
62 * single byte in length. If the data is longer than that byte, it is
63 * truncated approprately.
64 */
65inline void add_stringlen_to_sockbuf(const char *buf, SockList *sl)
66{
67 int len;
68
69 len=strlen(buf);
70 if (len>255) len=255;
71 SockList_AddChar(sl, (char) len);
72 strncpy((char*)sl->buf+sl->len, buf,len);
73 sl->len += len;
74}
75
76/**
77 * This is a similar to query_name, but returns flags 49 * This is a similar to query_name, but returns flags
78 * to be sended to client. 50 * to be sent to client.
79 */ 51 */
52unsigned int
80unsigned int query_flags (object *op) 53query_flags (object *op)
81{ 54{
82 unsigned int flags = 0; 55 unsigned int flags = 0;
83 56
84 if(QUERY_FLAG(op,FLAG_APPLIED)) { 57 if (QUERY_FLAG (op, FLAG_APPLIED))
58 {
85 switch(op->type) { 59 switch (op->type)
60 {
86 case BOW: 61 case BOW:
87 case WAND: 62 case WAND:
88 case ROD: 63 case ROD:
89 case HORN: 64 case HORN:
90 flags = a_readied; 65 flags = a_readied;
111 default: 86 default:
112 flags = a_applied; 87 flags = a_applied;
113 break; 88 break;
114 } 89 }
115 } 90 }
91
116 if (op->type == CONTAINER && ((op->env && op->env->container == op) || 92 if (op->type == CONTAINER && ((op->env && op->env->container == op) || (!op->env && QUERY_FLAG (op, FLAG_APPLIED))))
117 (!op->env && QUERY_FLAG(op,FLAG_APPLIED))))
118 flags |= F_OPEN; 93 flags |= F_OPEN;
119 94
120 if (QUERY_FLAG(op,FLAG_KNOWN_CURSED)) { 95 if (QUERY_FLAG (op, FLAG_KNOWN_CURSED))
96 {
121 if(QUERY_FLAG(op,FLAG_DAMNED)) 97 if (QUERY_FLAG (op, FLAG_DAMNED))
122 flags |= F_DAMNED; 98 flags |= F_DAMNED;
123 else if(QUERY_FLAG(op,FLAG_CURSED)) 99 else if (QUERY_FLAG (op, FLAG_CURSED))
124 flags |= F_CURSED; 100 flags |= F_CURSED;
125 } 101 }
102
126 if (QUERY_FLAG(op,FLAG_KNOWN_MAGICAL) && !QUERY_FLAG(op,FLAG_IDENTIFIED)) 103 if (QUERY_FLAG (op, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (op, FLAG_IDENTIFIED))
127 flags |= F_MAGIC; 104 flags |= F_MAGIC;
128 if (QUERY_FLAG(op,FLAG_UNPAID)) 105 if (QUERY_FLAG (op, FLAG_UNPAID))
129 flags |= F_UNPAID; 106 flags |= F_UNPAID;
130 if (QUERY_FLAG(op,FLAG_INV_LOCKED)) 107 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
131 flags |= F_LOCKED; 108 flags |= F_LOCKED;
132 109
133 return flags; 110 return flags;
134} 111}
135 112
136/* Used in the send_look to put object head into SockList 113/* Used in the send_look to put object head into packet
137 * sl for socket ns. Need socket to know if we need to send 114 * sl for socket ns. Need socket to know if we need to send
138 * animation of face to the client. 115 * animation of face to the client.
139 */ 116 */
140static void add_object_to_socklist(NewSocket *ns, SockList *sl, object *head) 117static void
118add_object_to_socklist (client &ns, packet &sl, object *head)
141{ 119{
142 int flags, len, anim_speed; 120 int flags, len, anim_speed;
143 char item_n[MAX_BUF]; 121 char item_n[MAX_BUF];
144 const char *item_p; 122 const char *item_p;
145 123
146 flags = query_flags (head); 124 flags = query_flags (head);
147 if (QUERY_FLAG(head, FLAG_NO_PICK)) 125 if (QUERY_FLAG (head, FLAG_NO_PICK))
148 flags |= F_NOPICK; 126 flags |= F_NOPICK;
149 127
150 if (!(ns->faces_sent[head->face->number] & NS_FACESENT_FACE)) 128 if (!(ns.faces_sent[head->face->number] & NS_FACESENT_FACE))
151 esrv_send_face(ns, head->face->number,0); 129 esrv_send_face (&ns, head->face->number, 0);
152 130
153 if (QUERY_FLAG(head,FLAG_ANIMATE) && !ns->anims_sent[head->animation_id]) 131 if (QUERY_FLAG (head, FLAG_ANIMATE) && !ns.anims_sent[head->animation_id])
154 esrv_send_animation(ns, head->animation_id); 132 esrv_send_animation (&ns, head->animation_id);
155 133
156 SockList_AddInt(sl, head->count); 134 sl << uint32 (head->count)
157 SockList_AddInt(sl, flags); 135 << uint32 (flags)
158 SockList_AddInt(sl, QUERY_FLAG(head, FLAG_NO_PICK) ? -1 : WEIGHT(head)); 136 << uint32 (QUERY_FLAG (head, FLAG_NO_PICK) ? -1 : WEIGHT (head))
159 SockList_AddInt(sl, head->face->number); 137 << uint32 (head->face->number);
160 138
161 if (!head->custom_name) { 139 if (!head->custom_name)
140 {
162 strncpy(item_n,query_base_name(head, 0),127); 141 strncpy (item_n, query_base_name (head, 0), 127);
163 item_n[127]=0; 142 item_n[127] = 0;
164 len=strlen(item_n); 143 len = strlen (item_n);
165 item_p=query_base_name(head, 1); 144 item_p = query_base_name (head, 1);
166 } else { 145 }
146 else
147 {
167 strncpy(item_n,head->custom_name,127); 148 strncpy (item_n, head->custom_name, 127);
168 item_n[127]=0; 149 item_n[127] = 0;
169 len=strlen(item_n); 150 len = strlen (item_n);
170 item_p=head->custom_name; 151 item_p = head->custom_name;
171 } 152 }
153
172 strncpy(item_n+len+1, item_p, 127); 154 strncpy (item_n + len + 1, item_p, 127);
173 item_n[254]=0; 155 item_n[254] = 0;
174 len += strlen(item_n+1+len) + 1; 156 len += strlen (item_n + 1 + len) + 1;
175 SockList_AddChar(sl, (char ) len);
176 memcpy(sl->buf+sl->len, item_n, len);
177 sl->len += len;
178 157
179 SockList_AddShort(sl,head->animation_id); 158 sl << data8 (item_n, len)
159 << uint16 (head->animation_id);
160
180 anim_speed=0; 161 anim_speed = 0;
181 if (QUERY_FLAG(head,FLAG_ANIMATE)) { 162 if (QUERY_FLAG (head, FLAG_ANIMATE))
163 {
164 if (head->anim_speed)
182 if (head->anim_speed) anim_speed=head->anim_speed; 165 anim_speed = head->anim_speed;
166 else
167 {
168 if (FABS (head->speed) < 0.001)
169 anim_speed = 255;
170 else if (FABS (head->speed) >= 1.0)
171 anim_speed = 1;
183 else { 172 else
184 if (FABS(head->speed)<0.001) anim_speed=255;
185 else if (FABS(head->speed)>=1.0) anim_speed=1;
186 else anim_speed = (int) (1.0/FABS(head->speed)); 173 anim_speed = (int) (1.0 / FABS (head->speed));
187 } 174 }
188 if (anim_speed>255) anim_speed=255;
189 }
190 SockList_AddChar(sl, (char) anim_speed);
191 SockList_AddInt(sl, head->nrof);
192 175
176 if (anim_speed > 255)
177 anim_speed = 255;
178 }
179
180 sl << uint8 (anim_speed)
181 << uint32 (head->nrof);
182
193 if (ns->itemcmd == 2) 183 if (ns.itemcmd == 2)
194 SockList_AddShort(sl, head->client_type); 184 sl << uint16 (head->client_type);
195 185
196 SET_FLAG(head, FLAG_CLIENT_SENT); 186 SET_FLAG (head, FLAG_CLIENT_SENT);
197} 187}
198 188
199 189
200/** 190/**
201 * Send the look window. Don't need to do animations here 191 * Send the look window. Don't need to do animations here
202 * This sends all the faces to the client, not just updates. This is 192 * This sends all the faces to the client, not just updates. This is
203 * because object ordering would otherwise be inconsistent 193 * because object ordering would otherwise be inconsistent.
204 */ 194 */
205 195void
206void esrv_draw_look(object *pl) 196esrv_draw_look (object *pl)
207{ 197{
208 object *tmp, *last; 198 object *tmp, *last;
209 int got_one=0,start_look=0, end_look=0; 199 int got_one = 0, start_look = 0, end_look = 0;
210 SockList sl;
211 char buf[MAX_BUF]; 200 char buf[MAX_BUF];
212 201
213 if (!pl->contr->socket.update_look) { 202 if (!pl->contr->socket->update_look)
203 {
214 LOG(llevDebug,"esrv_draw_look called when update_look was not set\n"); 204 LOG (llevDebug, "esrv_draw_look called when update_look was not set\n");
215 return; 205 return;
216 } else { 206 }
207 else
217 pl->contr->socket.update_look=0; 208 pl->contr->socket->update_look = 0;
218 }
219 209
220 if(QUERY_FLAG(pl, FLAG_REMOVED) || pl->map == NULL || 210 if (QUERY_FLAG (pl, FLAG_REMOVED)
221 pl->map->in_memory != MAP_IN_MEMORY || out_of_map(pl->map,pl->x,pl->y)) 211 || !pl->map
222 return; 212 || pl->map->in_memory != MAP_IN_MEMORY
213 || out_of_map (pl->map, pl->x, pl->y))
214 return;
223 215
224 for (tmp=get_map_ob(pl->map,pl->x,pl->y); tmp && tmp->above;tmp=tmp->above) ; 216 for (tmp = get_map_ob (pl->map, pl->x, pl->y); tmp && tmp->above; tmp = tmp->above)
217 ;
225 218
226 sl.buf= (unsigned char *) malloc(MAXSOCKBUF); 219 packet sl;
227 220
228 Write_String_To_Socket(&pl->contr->socket, "delinv 0", strlen("delinv 0")); 221 pl->contr->socket->send_packet ("delinv 0");
222
229 sprintf((char*)sl.buf,"item%d ", pl->contr->socket.itemcmd); 223 sl.printf ("item%d ", pl->contr->socket->itemcmd);
230 sl.len=strlen((char*)sl.buf);
231 224
232 SockList_AddInt(&sl, 0); 225 sl << uint32 (0);
233 226
234 if (!(pl->contr->socket.faces_sent[empty_face->number]&NS_FACESENT_FACE)) 227 if (!(pl->contr->socket->faces_sent[empty_face->number] & NS_FACESENT_FACE))
235 esrv_send_face(&pl->contr->socket, empty_face->number,0); 228 esrv_send_face (pl->contr->socket, empty_face->number, 0);
236 229
237 if (pl->contr->socket.look_position) { 230 if (pl->contr->socket->look_position)
238 SockList_AddInt(&sl, 0x80000000 | (pl->contr->socket.look_position- NUM_LOOK_OBJECTS)); 231 {
239 SockList_AddInt(&sl, 0); 232 char buf[80];
240 SockList_AddInt(&sl, (uint32) -1);
241 SockList_AddInt(&sl, empty_face->number);
242 sprintf(buf,"Click here to see %d previous items", NUM_LOOK_OBJECTS); 233 snprintf (buf, 80, "Apply this to see %d previous items", NUM_LOOK_OBJECTS);
243 add_stringlen_to_sockbuf(buf, &sl); 234
244 SockList_AddShort(&sl,0); 235 sl << uint32 (0x80000000 | (pl->contr->socket->look_position - NUM_LOOK_OBJECTS))
245 SockList_AddChar(&sl, 0); 236 << uint32 (0)
246 SockList_AddInt(&sl, 0); 237 << sint32 (-1)
238 << uint32 (empty_face->number)
239 << data8 (buf)
240 << uint16 (0)
241 << uint8 (0)
242 << uint32 (0);
243
247 if (pl->contr->socket.itemcmd == 2) 244 if (pl->contr->socket->itemcmd == 2)
248 SockList_AddShort(&sl, 0); 245 sl << uint16 (0);
249 } 246 }
250 247
251 for (last=NULL; tmp!=last; tmp=tmp->below) { 248 for (last = NULL; tmp != last; tmp = tmp->below)
249 {
252 object *head; 250 object *head;
253 251
254 if (QUERY_FLAG(tmp, FLAG_IS_FLOOR) && !last) { 252 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR) && !last)
253 {
255 last = tmp->below; /* assumes double floor mode */ 254 last = tmp->below; /* assumes double floor mode */
256 if (last && QUERY_FLAG(last, FLAG_IS_FLOOR)) 255 if (last && QUERY_FLAG (last, FLAG_IS_FLOOR))
257 last = last->below; 256 last = last->below;
258 } 257 }
258
259 if (LOOK_OBJ(tmp)) { 259 if (LOOK_OBJ (tmp))
260 {
260 if (++start_look < pl->contr->socket.look_position) continue; 261 if (++start_look < pl->contr->socket->look_position)
262 continue;
263
261 end_look++; 264 end_look++;
265
262 if (end_look > NUM_LOOK_OBJECTS) { 266 if (end_look > NUM_LOOK_OBJECTS)
267 {
263 /* What we basically do is make a 'fake' object - when the user applies it, 268 /* What we basically do is make a 'fake' object - when the user applies it,
264 * we notice the special tag the object has, and act accordingly. 269 * we notice the special tag the object has, and act accordingly.
265 */ 270 */
266 SockList_AddInt(&sl, 0x80000000 | (pl->contr->socket.look_position+ NUM_LOOK_OBJECTS)); 271 sl << uint32 (0x80000000 | (pl->contr->socket->look_position + NUM_LOOK_OBJECTS))
267 SockList_AddInt(&sl, 0); 272 << uint32 (0)
268 SockList_AddInt(&sl, (uint32) -1); 273 << uint32 ((uint32) - 1)
269 SockList_AddInt(&sl, empty_face->number); 274 << uint32 (empty_face->number)
270 sprintf(buf,"Click here to see next group of items"); 275 << data8 ("Apply this to see next group of items")
271 add_stringlen_to_sockbuf(buf, &sl); 276 << uint16 (0)
272 SockList_AddShort(&sl,0); 277 << uint8 (0)
273 SockList_AddChar(&sl, 0); 278 << uint32 (0);
274 SockList_AddInt(&sl, 0); 279
275 if (pl->contr->socket.itemcmd == 2) 280 if (pl->contr->socket->itemcmd == 2)
276 SockList_AddShort(&sl, 0); 281 sl << uint16 (0);
282
277 break; 283 break;
278 } 284 }
285
286 if (tmp->head)
279 if (tmp->head) head = tmp->head; 287 head = tmp->head;
288 else
280 else head = tmp; 289 head = tmp;
281 290
282 add_object_to_socklist(&pl->contr->socket, &sl, head); 291 add_object_to_socklist (*pl->contr->socket, sl, head);
283 got_one++; 292 got_one++;
284 293
285 if (sl.len >= (MAXSOCKBUF-MAXITEMLEN)) { 294 if (sl.length () >= (MAXSOCKBUF - MAXITEMLEN))
286 Send_With_Handling(&pl->contr->socket, &sl); 295 {
296 pl->contr->socket->send_packet (sl);
297
298 sl.reset ();
287 sprintf((char*)sl.buf,"item%d ", pl->contr->socket.itemcmd); 299 sl.printf ("item%d ", pl->contr->socket->itemcmd);
288 sl.len=strlen((char*)sl.buf); 300 sl << uint32 (0);
289 SockList_AddInt(&sl, 0);
290 got_one=0; 301 got_one = 0;
291 } 302 }
292 } /* If LOOK_OBJ() */ 303 }
293 } 304 }
305
294 if (got_one) 306 if (got_one)
295 Send_With_Handling(&pl->contr->socket, &sl); 307 pl->contr->socket->send_packet (sl);
296 308
297 free(sl.buf);
298} 309}
299 310
300/** 311/**
301 * Sends whole inventory. 312 * Sends whole inventory.
302 */ 313 */
314void
303void esrv_send_inventory(object *pl, object *op) 315esrv_send_inventory (object *pl, object *op)
304{ 316{
305 object *tmp; 317 object *tmp;
306 int got_one=0; 318 int got_one = 0;
307 SockList sl;
308
309 sl.buf= (unsigned char *) malloc(MAXSOCKBUF);
310 319
320 packet sl;
321
311 sprintf((char*)sl.buf,"delinv %d", op->count); 322 sl.printf ("delinv %d", op->count);
312 sl.len=strlen((char*)sl.buf); 323 pl->contr->socket->send_packet (sl);
313 Send_With_Handling(&pl->contr->socket, &sl);
314 324
325 sl.reset ();
315 sprintf((char*)sl.buf,"item%d ", pl->contr->socket.itemcmd); 326 sl.printf ("item%d ", pl->contr->socket->itemcmd);
316 sl.len=strlen((char*)sl.buf);
317 327
318 SockList_AddInt(&sl, op->count); 328 sl << uint32 (op->count);
319 329
320 for (tmp=op->inv; tmp; tmp=tmp->below) { 330 for (tmp = op->inv; tmp; tmp = tmp->below)
331 {
321 object *head; 332 object *head;
322 333
334 if (tmp->head)
323 if (tmp->head) head = tmp->head; 335 head = tmp->head;
336 else
324 else head = tmp; 337 head = tmp;
325 338
326 if (LOOK_OBJ(head)) { 339 if (LOOK_OBJ (head))
340 {
327 add_object_to_socklist(&pl->contr->socket, &sl, head); 341 add_object_to_socklist (*pl->contr->socket, sl, head);
328 342
329 got_one++; 343 got_one++;
330 344
331 /* IT is possible for players to accumulate a huge amount of 345 /* IT is possible for players to accumulate a huge amount of
332 * items (especially with some of the bags out there) to 346 * items (especially with some of the bags out there) to
333 * overflow the buffer. IF so, send multiple item commands. 347 * overflow the buffer. IF so, send multiple item commands.
334 */ 348 */
335 if (sl.len >= (MAXSOCKBUF-MAXITEMLEN)) { 349 if (sl.length () >= (MAXSOCKBUF - MAXITEMLEN))
336 Send_With_Handling(&pl->contr->socket, &sl); 350 {
351 pl->contr->socket->send_packet (sl);
352
353 sl.reset ();
337 sprintf((char*)sl.buf,"item%d ", pl->contr->socket.itemcmd); 354 sl.printf ("item%d ", pl->contr->socket->itemcmd);
338 sl.len=strlen((char*)sl.buf); 355 sl << uint32 (op->count);
339 SockList_AddInt(&sl, op->count);
340 got_one=0; 356 got_one = 0;
341 } 357 }
342 } /* If LOOK_OBJ() */ 358 } /* If LOOK_OBJ() */
343 } 359 }
360
344 if (got_one) 361 if (got_one)
345 Send_With_Handling(&pl->contr->socket, &sl); 362 pl->contr->socket->send_packet (sl);
346 free(sl.buf);
347} 363}
348 364
349/** 365/**
350 * Updates object *op for player *pl. 366 * Updates object *op for player *pl.
351 * 367 *
352 * flags is a list of values to update 368 * flags is a list of values to update
353 * to the client (as defined in newclient.h - might as well use the 369 * to the client (as defined in newclient.h - might as well use the
354 * same value both places. 370 * same value both places.
355 */ 371 */
356 372
373void
357void esrv_update_item(int flags, object *pl, object *op) 374esrv_update_item (int flags, object *pl, object *op)
358{ 375{
359 SockList sl;
360
361 /* If we have a request to send the player item, skip a few checks. */ 376 /* If we have a request to send the player item, skip a few checks. */
362 if (op!=pl) { 377 if (op != pl)
378 {
363 if (! LOOK_OBJ(op)) 379 if (!LOOK_OBJ (op))
364 return; 380 return;
365 /* we remove the check for op->env, because in theory, the object 381 /* we remove the check for op->env, because in theory, the object
366 * is hopefully in the same place, so the client should preserve 382 * is hopefully in the same place, so the client should preserve
367 * order. 383 * order.
368 */ 384 */
369 } 385 }
386
370 if (!QUERY_FLAG(op, FLAG_CLIENT_SENT)) { 387 if (!QUERY_FLAG (op, FLAG_CLIENT_SENT))
388 {
371 /* FLAG_CLIENT_SENT is debug only. We are using it to see where 389 /* FLAG_CLIENT_SENT is debug only. We are using it to see where
372 * this is happening - we can set a breakpoint here in the debugger 390 * this is happening - we can set a breakpoint here in the debugger
373 * and track back the call. 391 * and track back the call.
374 */ 392 */
375 LOG(llevDebug,"We have not sent item %s (%d)\n", &op->name, op->count); 393 LOG (llevDebug, "We have not sent item %s (%d)\n", &op->name, op->count);
376 } 394 }
377 sl.buf= (unsigned char *) malloc(MAXSOCKBUF);
378 395
379 strcpy((char*)sl.buf,"upditem "); 396 packet sl;
380 sl.len=strlen((char*)sl.buf);
381 397
382 SockList_AddChar(&sl, (char) flags); 398 sl << "upditem "
399 << uint8 (flags);
383 400
384 if (op->head) op=op->head; 401 if (op->head)
402 op = op->head;
385 403
386 SockList_AddInt(&sl, op->count); 404 sl << uint32 (op->count);
387 405
388 if (flags & UPD_LOCATION) 406 if (flags & UPD_LOCATION)
389 SockList_AddInt(&sl, op->env? op->env->count:0); 407 sl << uint32 (op->env ? op->env->count : 0);
390 408
391 if (flags & UPD_FLAGS) 409 if (flags & UPD_FLAGS)
392 SockList_AddInt(&sl, query_flags(op)); 410 sl << uint32 (query_flags (op));
393 411
394 if (flags & UPD_WEIGHT) { 412 if (flags & UPD_WEIGHT)
413 {
395 sint32 weight = WEIGHT(op); 414 sint32 weight = WEIGHT (op);
396 415
397 SockList_AddInt(&sl, QUERY_FLAG(op, FLAG_NO_PICK) ? -1 : weight); 416 sl << uint32 (QUERY_FLAG (op, FLAG_NO_PICK) ? -1 : weight);
417
398 if (pl == op) { 418 if (pl == op)
399 op->contr->last_weight = weight; 419 op->contr->last_weight = weight;
400 }
401 } 420 }
402 421
403 if (flags & UPD_FACE) { 422 if (flags & UPD_FACE)
423 {
404 if (!(pl->contr->socket.faces_sent[op->face->number] & NS_FACESENT_FACE)) 424 if (!(pl->contr->socket->faces_sent[op->face->number] & NS_FACESENT_FACE))
405 esrv_send_face(&pl->contr->socket, op->face->number,0); 425 esrv_send_face (pl->contr->socket, op->face->number, 0);
406 SockList_AddInt(&sl, op->face->number); 426
427 sl << uint32 (op->face->number);
407 } 428 }
429
408 if (flags & UPD_NAME) { 430 if (flags & UPD_NAME)
431 {
409 int len; 432 int len;
410 const char *item_p; 433 const char *item_p;
411 char item_n[MAX_BUF]; 434 char item_n[MAX_BUF];
412 435
413 if (!op->custom_name) { 436 if (!op->custom_name)
437 {
414 strncpy(item_n,query_base_name(op, 0),127); 438 strncpy (item_n, query_base_name (op, 0), 127);
415 item_n[127]=0; 439 item_n[127] = 0;
416 len=strlen(item_n); 440 len = strlen (item_n);
417 item_p=query_base_name(op, 1); 441 item_p = query_base_name (op, 1);
442 }
443 else
418 } 444 {
419 else {
420 strncpy(item_n,op->custom_name,127); 445 strncpy (item_n, op->custom_name, 127);
421 item_n[127]=0; 446 item_n[127] = 0;
422 len=strlen(item_n); 447 len = strlen (item_n);
423 item_p=op->custom_name; 448 item_p = op->custom_name;
424 } 449 }
425 450
426 strncpy(item_n+len+1, item_p, 127); 451 strncpy (item_n + len + 1, item_p, 127);
427 item_n[254]=0; 452 item_n[254] = 0;
428 len += strlen(item_n+1+len) + 1; 453 len += strlen (item_n + 1 + len) + 1;
429 SockList_AddChar(&sl, (char)len); 454
430 memcpy(sl.buf+sl.len, item_n, len); 455 sl << data8 (item_n, len);
431 sl.len += len;
432 } 456 }
457
433 if (flags & UPD_ANIM) 458 if (flags & UPD_ANIM)
434 SockList_AddShort(&sl,op->animation_id); 459 sl << uint16 (op->animation_id);
435 460
436 if (flags & UPD_ANIMSPEED) { 461 if (flags & UPD_ANIMSPEED)
462 {
437 int anim_speed=0; 463 int anim_speed = 0;
464
438 if (QUERY_FLAG(op,FLAG_ANIMATE)) { 465 if (QUERY_FLAG (op, FLAG_ANIMATE))
466 {
467 if (op->anim_speed)
439 if (op->anim_speed) anim_speed=op->anim_speed; 468 anim_speed = op->anim_speed;
469 else
470 {
471 if (FABS (op->speed) < 0.001)
472 anim_speed = 255;
473 else if (FABS (op->speed) >= 1.0)
474 anim_speed = 1;
440 else { 475 else
441 if (FABS(op->speed)<0.001) anim_speed=255;
442 else if (FABS(op->speed)>=1.0) anim_speed=1;
443 else anim_speed = (int) (1.0/FABS(op->speed)); 476 anim_speed = (int) (1.0 / FABS (op->speed));
444 } 477 }
445 if (anim_speed>255) anim_speed=255; 478
479 if (anim_speed > 255)
480 anim_speed = 255;
446 } 481 }
447 SockList_AddChar(&sl, (char)anim_speed); 482
483 sl << uint8 (anim_speed);
448 } 484 }
485
449 if (flags & UPD_NROF) 486 if (flags & UPD_NROF)
450 SockList_AddInt(&sl, op->nrof); 487 sl << uint32 (op->nrof);
451 488
452 Send_With_Handling(&pl->contr->socket, &sl); 489 pl->contr->socket->send_packet (sl);
453 free(sl.buf);
454} 490}
455 491
456/** 492/**
457 * Sends item's info to player. 493 * Sends item's info to player.
458 */ 494 */
495void
459void esrv_send_item(object *pl, object*op) 496esrv_send_item (object *pl, object *op)
460{ 497{
461 SockList sl;
462
463 /* If this is not the player object, do some more checks */ 498 /* If this is not the player object, do some more checks */
464 if (op!=pl) { 499 if (op != pl)
500 {
465 /* We only send 'visibile' objects to the client */ 501 /* We only send 'visibile' objects to the client */
466 if (! LOOK_OBJ(op)) 502 if (!LOOK_OBJ (op))
467 return; 503 return;
468 /* if the item is on the ground, mark that the look needs to 504 /* if the item is on the ground, mark that the look needs to
469 * be updated. 505 * be updated.
470 */ 506 */
471 if (!op->env) { 507 if (!op->env)
508 {
472 pl->contr->socket.update_look=1; 509 pl->contr->socket->update_look = 1;
473 return; 510 return;
474 } 511 }
475 } 512 }
476 513
477 sl.buf= (unsigned char *) malloc(MAXSOCKBUF); 514 packet sl;
478 515
479 sprintf((char*)sl.buf,"item%d ", pl->contr->socket.itemcmd); 516 sl.printf ("item%d ", pl->contr->socket->itemcmd);
480 sl.len=strlen((char*)sl.buf);
481 517
482 if (op->head) op=op->head; 518 if (op->head)
519 op = op->head;
483 520
484 SockList_AddInt(&sl, op->env? op->env->count:0); 521 sl << uint32 (op->env ? op->env->count : 0);
485 522
486 add_object_to_socklist(&pl->contr->socket, &sl, op); 523 add_object_to_socklist (*pl->contr->socket, sl, op);
487 524
488 Send_With_Handling(&pl->contr->socket, &sl); 525 pl->contr->socket->send_packet (sl);
489 SET_FLAG(op, FLAG_CLIENT_SENT); 526 SET_FLAG (op, FLAG_CLIENT_SENT);
490 free(sl.buf);
491} 527}
492 528
493/** 529/**
494 * Tells the client to delete an item. Uses the item 530 * Tells the client to delete an item. Uses the item
495 * command with a -1 location. 531 * command with a -1 location.
496 */ 532 */
497 533
534void
498void esrv_del_item(player *pl, int tag) 535esrv_del_item (player *pl, int tag)
499{ 536{
500 SockList sl; 537 packet sl;
501 538
502 sl.buf= (unsigned char *) malloc(MAXSOCKBUF); 539 sl << "delitem "
540 << uint32 (tag);
503 541
504 strcpy((char*)sl.buf,"delitem "); 542 pl->socket->send_packet (sl);
505 sl.len=strlen((char*)sl.buf);
506 SockList_AddInt(&sl, tag);
507
508 Send_With_Handling(&pl->socket, &sl);
509 free(sl.buf);
510} 543}
511 544
512 545
513/******************************************************************************* 546/*******************************************************************************
514 * 547 *
519/** 552/**
520 * Takes a player and object count (tag) and returns the actual object 553 * Takes a player and object count (tag) and returns the actual object
521 * pointer, or null if it can't be found. 554 * pointer, or null if it can't be found.
522 */ 555 */
523 556
557object *
524object *esrv_get_ob_from_count(object *pl, tag_t count) 558esrv_get_ob_from_count (object *pl, tag_t count)
525{ 559{
526 object *op, *tmp; 560 object *op, *tmp;
527 561
528 if (pl->count == count) 562 if (pl->count == count)
529 return pl; 563 return pl;
530 564
531 for(op = pl->inv; op; op = op->below) 565 for (op = pl->inv; op; op = op->below)
532 if (op->count == count) 566 if (op->count == count)
533 return op; 567 return op;
534 else if (op->type == CONTAINER && pl->container == op) 568 else if (op->type == CONTAINER && pl->container == op)
535 for(tmp = op->inv; tmp; tmp = tmp->below) 569 for (tmp = op->inv; tmp; tmp = tmp->below)
536 if (tmp->count == count) 570 if (tmp->count == count)
537 return tmp; 571 return tmp;
538 572
539 for(op = get_map_ob (pl->map, pl->x, pl->y); op; op = op->above) 573 for (op = get_map_ob (pl->map, pl->x, pl->y); op; op = op->above)
540 if (op->head != NULL && op->head->count == count) 574 if (op->head && op->head->count == count)
541 return op; 575 return op;
542 else if (op->count == count) 576 else if (op->count == count)
543 return op; 577 return op;
544 else if (op->type == CONTAINER && pl->container == op) 578 else if (op->type == CONTAINER && pl->container == op)
545 for(tmp = op->inv; tmp; tmp = tmp->below) 579 for (tmp = op->inv; tmp; tmp = tmp->below)
546 if (tmp->count == count) 580 if (tmp->count == count)
547 return tmp; 581 return tmp;
548 582
549 return NULL; 583 return 0;
550} 584}
551 585
552 586
553/** Client wants to examine some object. So lets do so. */ 587/** Client wants to examine some object. So lets do so. */
588void
554void ExamineCmd(char *buf, int len,player *pl) 589ExamineCmd (char *buf, int len, player *pl)
555{ 590{
556 long tag = atoi(buf); 591 tag_t tag = atoi (buf);
592
593 /* If the high bit is set, player examined a pseudo object. */
594 if (tag & 0x80000000)
595 return;
596
557 object *op = esrv_get_ob_from_count(pl->ob, tag); 597 object *op = esrv_get_ob_from_count (pl->ob, tag);
558 598
559 if (!op) { 599 if (!op)
600 {
560 LOG(llevDebug, "Player '%s' tried to examine the unknown object (%ld)\n", &pl->ob->name, tag); 601 LOG (llevDebug, "Player '%s' tried to examine the unknown object (%ld)\n", &pl->ob->name, tag);
561 return; 602 return;
562 } 603 }
604
563 examine (pl->ob, op); 605 examine (pl->ob, op);
606}
607
608/** Client wants to apply some object. Lets do so. */
609void
610ApplyCmd (char *buf, int len, player *pl)
611{
612 tag_t tag = atoi (buf);
613
614 /* sort of a hack, but if the player saves and the player then manually
615 * applies a savebed (or otherwise tries to do stuff), we run into trouble.
616 */
617 if (QUERY_FLAG (pl->ob, FLAG_REMOVED))
618 return;
619
620 /* If the high bit is set, player applied a pseudo object. */
621 if (tag & 0x80000000)
622 {
623 pl->socket->look_position = tag & 0x7fffffff;
624 pl->socket->update_look = 1;
625 return;
626 }
627
628 object *op = esrv_get_ob_from_count (pl->ob, tag);
629
630 if (!op)
631 {
632 LOG (llevDebug, "Player '%s' tried to apply the unknown object (%d)\n", &pl->ob->name, tag);
633 return;
634 }
635
636 player_apply (pl->ob, op, 0, 0);
564} 637}
565 638
566/** Client wants to apply some object. Lets do so. */ 639/** Client wants to apply some object. Lets do so. */
567void ApplyCmd(char *buf, int len,player *pl) 640void
641LockItem (char *data, int len, player *pl)
568{ 642{
569 uint32 tag = atoi(buf); 643 int flag = data[0];
644 tag_t tag = net_uint32 ((uint8 *)data + 1);
570 object *op = esrv_get_ob_from_count(pl->ob, tag); 645 object *op = esrv_get_ob_from_count (pl->ob, tag);
571 646
572 /* sort of a hack, but if the player saves and the player then manually 647 if (!op)
573 * applies a savebed (or otherwise tries to do stuff), we run into trouble. 648 {
574 */ 649 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Could not find object to lock/unlock");
575 if (QUERY_FLAG(pl->ob, FLAG_REMOVED)) return;
576
577 /* If the high bit is set, player applied a pseudo object. */
578 if (tag & 0x80000000) {
579 pl->socket.look_position = tag & 0x7fffffff;
580 pl->socket.update_look = 1;
581 return; 650 return;
582 } 651 }
583 652
584 if (!op) { 653 if (!flag)
585 LOG(llevDebug, "Player '%s' tried to apply the unknown object (%d)\n", &pl->ob->name, tag); 654 CLEAR_FLAG (op, FLAG_INV_LOCKED);
586 return; 655 else
587 } 656 SET_FLAG (op, FLAG_INV_LOCKED);
588 player_apply (pl->ob, op, 0, 0); 657
658 esrv_update_item (UPD_FLAGS, pl->ob, op);
589} 659}
590 660
591/** Client wants to apply some object. Lets do so. */ 661/** Client wants to apply some object. Lets do so. */
662void
592void LockItem(uint8 *data, int len,player *pl) 663MarkItem (char *data, int len, player *pl)
593{ 664{
594 int flag, tag; 665 tag_t tag = net_uint32 ((uint8 *)data);
595 object *op;
596
597 flag = data[0];
598 tag = GetInt_String(data+1);
599 op = esrv_get_ob_from_count(pl->ob, tag); 666 object *op = esrv_get_ob_from_count (pl->ob, tag);
600 667
601 if (!op) { 668 if (!op)
602 new_draw_info(NDI_UNIQUE, 0, pl->ob,"Could not find object to lock/unlock");
603 return;
604 } 669 {
605 if (!flag)
606 CLEAR_FLAG(op,FLAG_INV_LOCKED);
607 else
608 SET_FLAG(op,FLAG_INV_LOCKED);
609 esrv_update_item(UPD_FLAGS, pl->ob, op);
610}
611
612/** Client wants to apply some object. Lets do so. */
613void MarkItem(uint8 *data, int len,player *pl)
614{
615 int tag;
616 object *op;
617
618 tag = GetInt_String(data);
619 op = esrv_get_ob_from_count(pl->ob, tag);
620 if (!op) {
621 new_draw_info(NDI_UNIQUE, 0, pl->ob,"Could not find object to mark"); 670 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Could not find object to mark");
622 return; 671 return;
623 } 672 }
673
624 pl->mark = op; 674 pl->mark = op;
625 pl->mark_count = op->count;
626 new_draw_info_format(NDI_UNIQUE, 0, pl->ob, "Marked item %s", query_name(op)); 675 new_draw_info_format (NDI_UNIQUE, 0, pl->ob, "Marked item %s", query_name (op));
627} 676}
628
629 677
630/** 678/**
631 * look_at prints items on the specified square. 679 * look_at prints items on the specified square.
632 * 680 *
633 * [ removed EARTHWALL check and added check for containers inventory. 681 * [ removed EARTHWALL check and added check for containers inventory.
634 * Tero.Haatanen@lut.fi ] 682 * Tero.Haatanen@lut.fi ]
635 */ 683 */
684void
636void look_at(object *op,int dx,int dy) { 685look_at (object *op, int dx, int dy)
686{
637 object *tmp; 687 object *tmp;
638 int flag=0; 688 int flag = 0;
639 sint16 x,y; 689 sint16 x, y;
640 mapstruct *m; 690 maptile *m;
641 691
642 x = op->x + dx; 692 x = op->x + dx;
643 y = op->y + dy; 693 y = op->y + dy;
644 694
645 if (out_of_map(op->map, x, y)) return; 695 if (out_of_map (op->map, x, y))
696 return;
646 697
647 m = get_map_from_coord(op->map, &x, &y); 698 m = get_map_from_coord (op->map, &x, &y);
648 if (!m) return; 699 if (!m)
700 return;
649 701
650 for(tmp=get_map_ob(m, x ,y);tmp!=NULL&&tmp->above!=NULL; 702 for (tmp = get_map_ob (m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above);
651 tmp=tmp->above);
652 703
653 for ( ; tmp != NULL; tmp=tmp->below ) { 704 for (; tmp != NULL; tmp = tmp->below)
705 {
654 if (tmp->invisible && !QUERY_FLAG(op, FLAG_WIZ)) continue; 706 if (tmp->invisible && !QUERY_FLAG (op, FLAG_WIZ))
707 continue;
655 708
656 if(!flag) { 709 if (!flag)
710 {
657 if(dx||dy) 711 if (dx || dy)
658 new_draw_info(NDI_UNIQUE, 0,op,"There you see:"); 712 new_draw_info (NDI_UNIQUE, 0, op, "There you see:");
659 else { 713 else
714 {
660 clear_win_info(op); 715 clear_win_info (op);
661 new_draw_info(NDI_UNIQUE, 0,op,"You see:"); 716 new_draw_info (NDI_UNIQUE, 0, op, "You see:");
662 } 717 }
663 flag=1; 718 flag = 1;
664 } 719 }
665 720
666 if (QUERY_FLAG(op, FLAG_WIZ)) 721 if (QUERY_FLAG (op, FLAG_WIZ))
667 new_draw_info_format(NDI_UNIQUE,0, op, "- %s (%d).",query_name(tmp),tmp->count); 722 new_draw_info_format (NDI_UNIQUE, 0, op, "- %s (%d).", query_name (tmp), tmp->count);
668 else 723 else
669 new_draw_info_format(NDI_UNIQUE,0, op, "- %s.",query_name(tmp)); 724 new_draw_info_format (NDI_UNIQUE, 0, op, "- %s.", query_name (tmp));
670 725
671 if (((tmp->inv!=NULL || (tmp->head && tmp->head->inv)) && 726 if (((tmp->inv != NULL || (tmp->head && tmp->head->inv)) &&
672 (tmp->type != CONTAINER && tmp->type!=FLESH)) || QUERY_FLAG(op, FLAG_WIZ)) 727 (tmp->type != CONTAINER && tmp->type != FLESH)) || QUERY_FLAG (op, FLAG_WIZ))
673 inventory(op,tmp->head==NULL?tmp:tmp->head); 728 inventory (op, tmp->head == NULL ? tmp : tmp->head);
674 729
675 if(QUERY_FLAG(tmp, FLAG_IS_FLOOR)&&!QUERY_FLAG(op, FLAG_WIZ)) /* don't continue under the floor */ 730 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR) && !QUERY_FLAG (op, FLAG_WIZ)) /* don't continue under the floor */
676 break; 731 break;
677 } 732 }
678 733
679 if(!flag) { 734 if (!flag)
735 {
680 if(dx||dy) 736 if (dx || dy)
681 new_draw_info(NDI_UNIQUE, 0,op,"You see nothing there."); 737 new_draw_info (NDI_UNIQUE, 0, op, "You see nothing there.");
682 else 738 else
683 new_draw_info(NDI_UNIQUE, 0,op,"You see nothing."); 739 new_draw_info (NDI_UNIQUE, 0, op, "You see nothing.");
684 } 740 }
685} 741}
686 742
687 743
688 744
689/** Client wants to look at some object. Lets do so. */ 745/** Client wants to look at some object. Lets do so. */
746void
690void LookAt(char *buf, int len,player *pl) 747LookAt (char *buf, int len, player *pl)
691{ 748{
692 int dx, dy; 749 int dx, dy;
693 char *cp; 750 char *cp;
694 751
695 dx=atoi(buf); 752 dx = atoi (buf);
696 if (!(cp=strchr(buf,' '))) { 753 if (!(cp = strchr (buf, ' ')))
754 {
755 return;
756 }
757 dy = atoi (cp);
758
759 if (FABS (dx) > pl->socket->mapx / 2 || FABS (dy) > pl->socket->mapy / 2)
760 return;
761
762 if (pl->blocked_los[dx + pl->socket->mapx / 2][dy + pl->socket->mapy / 2])
763 return;
764
765 look_at (pl->ob, dx, dy);
766}
767
768/** Move an object to a new location */
769void
770esrv_move_object (object *pl, tag_t to, tag_t tag, long nrof)
771{
772 object *op, *env;
773
774 op = esrv_get_ob_from_count (pl, tag);
775 if (!op)
776 {
777 LOG (llevDebug, "Player '%s' tried to move an unknown object (%ld)\n", &pl->name, tag);
778 return;
779 }
780
781 if (!to)
782 { /* drop it to the ground */
783 if (op->map && !op->env)
697 return; 784 return;
698 }
699 dy=atoi(cp);
700 785
701 if (FABS(dx) > pl->socket.mapx / 2 || FABS(dy) > pl->socket.mapy / 2) 786 /* If it is an active container, then we should drop all objects
787 * in the container and not the container itself.
788 */
789 if (op->inv && QUERY_FLAG (op, FLAG_APPLIED))
790 {
791 object *current, *next;
792
793 for (current = op->inv; current != NULL; current = next)
794 {
795 next = current->below;
796 drop_object (pl, current, 0);
797 }
798
799 esrv_update_item (UPD_WEIGHT, pl, op);
800 }
801 else
802 drop_object (pl, op, nrof);
803
702 return; 804 return;
703 805 }
704 if(pl->blocked_los[dx + pl->socket.mapx / 2][dy + pl->socket.mapy / 2]) 806 else if (to == pl->count)
705 return; 807 { /* pick it up to the inventory */
706 808 /* return if player has already picked it up */
707 look_at(pl->ob, dx, dy); 809 if (op->env == pl)
708}
709
710/** Move an object to a new location */
711void esrv_move_object (object *pl, tag_t to, tag_t tag, long nrof)
712{
713 object *op, *env;
714
715 op = esrv_get_ob_from_count(pl, tag);
716 if (!op) {
717 LOG(llevDebug, "Player '%s' tried to move an unknown object (%ld)\n", &pl->name, tag);
718 return; 810 return;
719 }
720 811
721 if (!to) { /* drop it to the ground */
722/* LOG(llevDebug, "Drop it on the ground.\n");*/
723
724 if (op->map && !op->env) {
725/* LOG(llevDebug,"Dropping object to ground that is already on ground\n");*/
726 return;
727 }
728 /* If it is an active container, then we should drop all objects
729 * in the container and not the container itself.
730 */
731 if (op->inv && QUERY_FLAG(op, FLAG_APPLIED)) {
732 object *current, *next;
733 for (current=op->inv; current!=NULL; current=next) {
734 next=current->below;
735 drop_object(pl, current, 0);
736 }
737 esrv_update_item(UPD_WEIGHT, pl, op);
738 }
739 else {
740 drop_object (pl, op, nrof);
741 }
742 return;
743 } else if (to == pl->count) { /* pick it up to the inventory */
744 /* return if player has already picked it up */
745 if (op->env == pl) return;
746
747 pl->contr->count = nrof; 812 pl->contr->count = nrof;
748 pick_up(pl, op); 813 pick_up (pl, op);
749 return ; 814 return;
750 } 815 }
816
751 env = esrv_get_ob_from_count(pl, to); 817 env = esrv_get_ob_from_count (pl, to);
752 if (!env) { 818 if (!env)
753 LOG(llevDebug, 819 {
754 "Player '%s' tried to move object to the unknown location (%d)\n", &pl->name, to); 820 LOG (llevDebug, "Player '%s' tried to move object to the unknown location (%d)\n", &pl->name, to);
755 return; 821 return;
756 } 822 }
823
757 /* put_object_in_sack presumes that necessary sanity checking 824 /* put_object_in_sack presumes that necessary sanity checking
758 * has already been done (eg, it can be picked up and fits in 825 * has already been done (eg, it can be picked up and fits in
759 * in a sack, so check for those things. We should also check 826 * in a sack, so check for those things. We should also check
760 * an make sure env is in fact a container for that matter. 827 * an make sure env is in fact a container for that matter.
761 */ 828 */
762 if (env->type == CONTAINER
763 && can_pick(pl, op) && sack_can_hold(pl, env, op, nrof)) { 829 if (env->type == CONTAINER && can_pick (pl, op) && sack_can_hold (pl, env, op, nrof))
764 put_object_in_sack (pl, env, op, nrof); 830 put_object_in_sack (pl, env, op, nrof);
765 }
766} 831}
767 832
768

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines