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.5 by root, Sun Sep 10 13:43:33 2006 UTC vs.
Revision 1.31 by root, Mon Jan 8 18:18:36 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines