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.30 by pippijn, Sat Jan 6 14:42:31 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
406 if (!QUERY_FLAG (op, FLAG_CLIENT_SENT)) 525 if (!QUERY_FLAG (op, FLAG_CLIENT_SENT))
407 { 526 {
408 /* FLAG_CLIENT_SENT is debug only. We are using it to see where 527 /* 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 528 * this is happening - we can set a breakpoint here in the debugger
410 * and track back the call. 529 * and track back the call.
411 */ 530 */
412 LOG (llevDebug, "We have not sent item %s (%d)\n", &op->name, op->count); 531 LOG (llevDebug, "We have not sent item %s (%d)\n", &op->name, op->count);
413 } 532 }
414 sl.buf = (unsigned char *) malloc (MAXSOCKBUF);
415 533
416 strcpy ((char *) sl.buf, "upditem "); 534 packet sl ("upditem");
417 sl.len = strlen ((char *) sl.buf);
418 535
419 SockList_AddChar (&sl, (char) flags); 536 sl << uint8 (flags);
420 537
421 if (op->head) 538 if (op->head)
422 op = op->head; 539 op = op->head;
423 540
424 SockList_AddInt (&sl, op->count); 541 sl << uint32 (op->count);
425 542
426 if (flags & UPD_LOCATION) 543 if (flags & UPD_LOCATION)
427 SockList_AddInt (&sl, op->env ? op->env->count : 0); 544 sl << uint32 (op->env ? op->env->count : 0);
428 545
429 if (flags & UPD_FLAGS) 546 if (flags & UPD_FLAGS)
430 SockList_AddInt (&sl, query_flags (op)); 547 sl << uint32 (query_flags (op));
431 548
432 if (flags & UPD_WEIGHT) 549 if (flags & UPD_WEIGHT)
433 { 550 {
434 sint32 weight = WEIGHT (op); 551 sint32 weight = WEIGHT (op);
435 552
436 SockList_AddInt (&sl, QUERY_FLAG (op, FLAG_NO_PICK) ? -1 : weight); 553 sl << uint32 (QUERY_FLAG (op, FLAG_NO_PICK) ? -1 : weight);
554
437 if (pl == op) 555 if (pl == op)
438 {
439 op->contr->last_weight = weight; 556 op->contr->last_weight = weight;
440 }
441 } 557 }
442 558
443 if (flags & UPD_FACE) 559 if (flags & UPD_FACE)
444 { 560 {
445 if (!(pl->contr->socket.faces_sent[op->face->number] & NS_FACESENT_FACE)) 561 if (!(pl->contr->ns->faces_sent[op->face->number] & NS_FACESENT_FACE))
446 esrv_send_face (&pl->contr->socket, op->face->number, 0); 562 esrv_send_face (pl->contr->ns, op->face->number, 0);
447 SockList_AddInt (&sl, op->face->number); 563
564 sl << uint32 (op->face->number);
448 } 565 }
566
449 if (flags & UPD_NAME) 567 if (flags & UPD_NAME)
450 { 568 {
451 int len; 569 int len;
452 const char *item_p; 570 const char *item_p;
453 char item_n[MAX_BUF]; 571 char item_n[MAX_BUF];
468 } 586 }
469 587
470 strncpy (item_n + len + 1, item_p, 127); 588 strncpy (item_n + len + 1, item_p, 127);
471 item_n[254] = 0; 589 item_n[254] = 0;
472 len += strlen (item_n + 1 + len) + 1; 590 len += strlen (item_n + 1 + len) + 1;
473 SockList_AddChar (&sl, (char) len); 591
474 memcpy (sl.buf + sl.len, item_n, len); 592 sl << data8 (item_n, len);
475 sl.len += len;
476 } 593 }
594
477 if (flags & UPD_ANIM) 595 if (flags & UPD_ANIM)
478 SockList_AddShort (&sl, op->animation_id); 596 sl << uint16 (op->animation_id);
479 597
480 if (flags & UPD_ANIMSPEED) 598 if (flags & UPD_ANIMSPEED)
481 { 599 {
482 int anim_speed = 0; 600 int anim_speed = 0;
483 601
492 else if (FABS (op->speed) >= 1.0) 610 else if (FABS (op->speed) >= 1.0)
493 anim_speed = 1; 611 anim_speed = 1;
494 else 612 else
495 anim_speed = (int) (1.0 / FABS (op->speed)); 613 anim_speed = (int) (1.0 / FABS (op->speed));
496 } 614 }
615
497 if (anim_speed > 255) 616 if (anim_speed > 255)
498 anim_speed = 255; 617 anim_speed = 255;
499 } 618 }
500 SockList_AddChar (&sl, (char) anim_speed); 619
620 sl << uint8 (anim_speed);
501 } 621 }
622
502 if (flags & UPD_NROF) 623 if (flags & UPD_NROF)
503 SockList_AddInt (&sl, op->nrof); 624 sl << uint32 (op->nrof);
504 625
505 Send_With_Handling (&pl->contr->socket, &sl); 626 pl->contr->ns->send_packet (sl);
506 free (sl.buf);
507} 627}
508 628
509/** 629/**
510 * Sends item's info to player. 630 * Sends item's info to player.
511 */ 631 */
512void 632void
513esrv_send_item (object *pl, object *op) 633esrv_send_item (object *pl, object *op)
514{ 634{
515 SockList sl;
516
517 /* If this is not the player object, do some more checks */ 635 /* If this is not the player object, do some more checks */
518 if (op != pl) 636 if (op != pl)
519 { 637 {
520 /* We only send 'visibile' objects to the client */ 638 /* We only send 'visibile' objects to the client */
521 if (!LOOK_OBJ (op)) 639 if (!LOOK_OBJ (op))
523 /* if the item is on the ground, mark that the look needs to 641 /* if the item is on the ground, mark that the look needs to
524 * be updated. 642 * be updated.
525 */ 643 */
526 if (!op->env) 644 if (!op->env)
527 { 645 {
528 pl->contr->socket.update_look = 1; 646 pl->contr->ns->floorbox_update ();
529 return; 647 return;
530 } 648 }
531 } 649 }
532 650
533 sl.buf = (unsigned char *) malloc (MAXSOCKBUF); 651 packet sl;
534 652
535 sprintf ((char *) sl.buf, "item%d ", pl->contr->socket.itemcmd); 653 sl.printf ("item%d ", pl->contr->ns->itemcmd);
536 sl.len = strlen ((char *) sl.buf);
537 654
538 if (op->head) 655 if (op->head)
539 op = op->head; 656 op = op->head;
540 657
541 SockList_AddInt (&sl, op->env ? op->env->count : 0); 658 sl << uint32 (op->env ? op->env->count : 0);
542 659
543 add_object_to_socklist (&pl->contr->socket, &sl, op); 660 add_object_to_socklist (*pl->contr->ns, sl, op);
544 661
545 Send_With_Handling (&pl->contr->socket, &sl); 662 pl->contr->ns->send_packet (sl);
546 SET_FLAG (op, FLAG_CLIENT_SENT); 663 SET_FLAG (op, FLAG_CLIENT_SENT);
547 free (sl.buf);
548} 664}
549 665
550/** 666/**
551 * Tells the client to delete an item. Uses the item 667 * Tells the client to delete an item. Uses the item
552 * command with a -1 location. 668 * command with a -1 location.
553 */ 669 */
554 670
555void 671void
556esrv_del_item (player *pl, int tag) 672esrv_del_item (player *pl, int tag)
557{ 673{
558 SockList sl; 674 packet sl ("delitem");
559 675
560 sl.buf = (unsigned char *) malloc (MAXSOCKBUF); 676 sl << uint32 (tag);
561 677
562 strcpy ((char *) sl.buf, "delitem "); 678 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} 679}
569 680
570 681
571/******************************************************************************* 682/*******************************************************************************
572 * 683 *
593 else if (op->type == CONTAINER && pl->container == op) 704 else if (op->type == CONTAINER && pl->container == op)
594 for (tmp = op->inv; tmp; tmp = tmp->below) 705 for (tmp = op->inv; tmp; tmp = tmp->below)
595 if (tmp->count == count) 706 if (tmp->count == count)
596 return tmp; 707 return tmp;
597 708
598 for (op = get_map_ob (pl->map, pl->x, pl->y); op; op = op->above) 709 for (op = GET_MAP_OB (pl->map, pl->x, pl->y); op; op = op->above)
599 if (op->head != NULL && op->head->count == count) 710 if (op->head && op->head->count == count)
600 return op; 711 return op;
601 else if (op->count == count) 712 else if (op->count == count)
602 return op; 713 return op;
603 else if (op->type == CONTAINER && pl->container == op) 714 else if (op->type == CONTAINER && pl->container == op)
604 for (tmp = op->inv; tmp; tmp = tmp->below) 715 for (tmp = op->inv; tmp; tmp = tmp->below)
605 if (tmp->count == count) 716 if (tmp->count == count)
606 return tmp; 717 return tmp;
607 718
608 return NULL; 719 return 0;
609} 720}
610 721
611 722
612/** Client wants to examine some object. So lets do so. */ 723/** Client wants to examine some object. So lets do so. */
613void 724void
614ExamineCmd (char *buf, int len, player *pl) 725ExamineCmd (char *buf, int len, player *pl)
615{ 726{
616 long tag = atoi (buf); 727 tag_t tag = atoi (buf);
728
729 /* If the high bit is set, player examined a pseudo object. */
730 if (tag & 0x80000000)
731 return;
732
617 object *op = esrv_get_ob_from_count (pl->ob, tag); 733 object *op = esrv_get_ob_from_count (pl->ob, tag);
618 734
619 if (!op) 735 if (!op)
620 { 736 {
621 LOG (llevDebug, "Player '%s' tried to examine the unknown object (%ld)\n", &pl->ob->name, tag); 737 LOG (llevDebug, "Player '%s' tried to examine the unknown object (%ld)\n", &pl->ob->name, tag);
622 return; 738 return;
623 } 739 }
740
624 examine (pl->ob, op); 741 examine (pl->ob, op);
625} 742}
626 743
627/** Client wants to apply some object. Lets do so. */ 744/** Client wants to apply some object. Lets do so. */
628void 745void
629ApplyCmd (char *buf, int len, player *pl) 746ApplyCmd (char *buf, int len, player *pl)
630{ 747{
631 uint32 tag = atoi (buf); 748 tag_t tag = atoi (buf);
632 object *op = esrv_get_ob_from_count (pl->ob, tag);
633 749
634 /* sort of a hack, but if the player saves and the player then manually 750 /* 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. 751 * applies a savebed (or otherwise tries to do stuff), we run into trouble.
636 */ 752 */
637 if (QUERY_FLAG (pl->ob, FLAG_REMOVED)) 753 if (QUERY_FLAG (pl->ob, FLAG_REMOVED))
638 return; 754 return;
639 755
640 /* If the high bit is set, player applied a pseudo object. */ 756 /* If the high bit is set, player applied a pseudo object. */
641 if (tag & 0x80000000) 757 if (tag & 0x80000000)
642 { 758 {
643 pl->socket.look_position = tag & 0x7fffffff; 759 pl->ns->look_position = tag & 0x7fffffff;
644 pl->socket.update_look = 1; 760 pl->ns->floorbox_update ();
645 return; 761 return;
646 } 762 }
763
764 object *op = esrv_get_ob_from_count (pl->ob, tag);
647 765
648 if (!op) 766 if (!op)
649 { 767 {
650 LOG (llevDebug, "Player '%s' tried to apply the unknown object (%d)\n", &pl->ob->name, tag); 768 LOG (llevDebug, "Player '%s' tried to apply the unknown object (%d)\n", &pl->ob->name, tag);
651 return; 769 return;
652 } 770 }
771
653 player_apply (pl->ob, op, 0, 0); 772 player_apply (pl->ob, op, 0, 0);
654} 773}
655 774
656/** Client wants to apply some object. Lets do so. */ 775/** Client wants to lock some object. Lets do so. */
657void 776void
658LockItem (uint8 * data, int len, player *pl) 777LockItem (char *data, int len, player *pl)
659{ 778{
660 int flag, tag;
661 object *op;
662
663 flag = data[0]; 779 int flag = data[0];
664 tag = GetInt_String (data + 1); 780 tag_t tag = net_uint32 ((uint8 *)data + 1);
665 op = esrv_get_ob_from_count (pl->ob, tag); 781 object *op = esrv_get_ob_from_count (pl->ob, tag);
666 782
667 if (!op) 783 if (!op)
668 { 784 {
669 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Could not find object to lock/unlock"); 785 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Could not find object to lock/unlock");
670 return; 786 return;
671 } 787 }
788
672 if (!flag) 789 if (!flag)
673 CLEAR_FLAG (op, FLAG_INV_LOCKED); 790 CLEAR_FLAG (op, FLAG_INV_LOCKED);
674 else 791 else
675 SET_FLAG (op, FLAG_INV_LOCKED); 792 SET_FLAG (op, FLAG_INV_LOCKED);
793
676 esrv_update_item (UPD_FLAGS, pl->ob, op); 794 esrv_update_item (UPD_FLAGS, pl->ob, op);
677} 795}
678 796
679/** Client wants to apply some object. Lets do so. */ 797/** Client wants to mark some object. Lets do so. */
680void 798void
681MarkItem (uint8 * data, int len, player *pl) 799MarkItem (char *data, int len, player *pl)
682{ 800{
683 int tag; 801 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); 802 object *op = esrv_get_ob_from_count (pl->ob, tag);
803
688 if (!op) 804 if (!op)
689 { 805 {
690 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Could not find object to mark"); 806 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Could not find object to mark");
691 return; 807 return;
692 } 808 }
809
693 pl->mark = op; 810 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)); 811 new_draw_info_format (NDI_UNIQUE, 0, pl->ob, "Marked item %s", query_name (op));
696} 812}
697
698 813
699/** 814/**
700 * look_at prints items on the specified square. 815 * look_at prints items on the specified square.
701 * 816 *
702 * [ removed EARTHWALL check and added check for containers inventory. 817 * [ removed EARTHWALL check and added check for containers inventory.
706look_at (object *op, int dx, int dy) 821look_at (object *op, int dx, int dy)
707{ 822{
708 object *tmp; 823 object *tmp;
709 int flag = 0; 824 int flag = 0;
710 sint16 x, y; 825 sint16 x, y;
711 mapstruct *m; 826 maptile *m;
712 827
713 x = op->x + dx; 828 x = op->x + dx;
714 y = op->y + dy; 829 y = op->y + dy;
715 830
716 if (out_of_map (op->map, x, y)) 831 if (out_of_map (op->map, x, y))
718 833
719 m = get_map_from_coord (op->map, &x, &y); 834 m = get_map_from_coord (op->map, &x, &y);
720 if (!m) 835 if (!m)
721 return; 836 return;
722 837
723 for (tmp = get_map_ob (m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above); 838 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above);
724 839
725 for (; tmp != NULL; tmp = tmp->below) 840 for (; tmp != NULL; tmp = tmp->below)
726 { 841 {
727 if (tmp->invisible && !QUERY_FLAG (op, FLAG_WIZ)) 842 if (tmp->invisible && !QUERY_FLAG (op, FLAG_WIZ))
728 continue; 843 continue;
775 { 890 {
776 return; 891 return;
777 } 892 }
778 dy = atoi (cp); 893 dy = atoi (cp);
779 894
780 if (FABS (dx) > pl->socket.mapx / 2 || FABS (dy) > pl->socket.mapy / 2) 895 if (FABS (dx) > pl->ns->mapx / 2 || FABS (dy) > pl->ns->mapy / 2)
781 return; 896 return;
782 897
783 if (pl->blocked_los[dx + pl->socket.mapx / 2][dy + pl->socket.mapy / 2]) 898 if (pl->blocked_los[dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2])
784 return; 899 return;
785 900
786 look_at (pl->ob, dx, dy); 901 look_at (pl->ob, dx, dy);
787} 902}
788 903
799 return; 914 return;
800 } 915 }
801 916
802 if (!to) 917 if (!to)
803 { /* drop it to the ground */ 918 { /* drop it to the ground */
804
805/* LOG(llevDebug, "Drop it on the ground.\n");*/
806
807 if (op->map && !op->env) 919 if (op->map && !op->env)
808 {
809
810/* LOG(llevDebug,"Dropping object to ground that is already on ground\n");*/
811 return; 920 return;
812 } 921
813 /* If it is an active container, then we should drop all objects 922 /* If it is an active container, then we should drop all objects
814 * in the container and not the container itself. 923 * in the container and not the container itself.
815 */ 924 */
816 if (op->inv && QUERY_FLAG (op, FLAG_APPLIED)) 925 if (op->inv && QUERY_FLAG (op, FLAG_APPLIED))
817 { 926 {
820 for (current = op->inv; current != NULL; current = next) 929 for (current = op->inv; current != NULL; current = next)
821 { 930 {
822 next = current->below; 931 next = current->below;
823 drop_object (pl, current, 0); 932 drop_object (pl, current, 0);
824 } 933 }
934
825 esrv_update_item (UPD_WEIGHT, pl, op); 935 esrv_update_item (UPD_WEIGHT, pl, op);
826 } 936 }
827 else 937 else
828 {
829 drop_object (pl, op, nrof); 938 drop_object (pl, op, nrof);
830 } 939
831 return; 940 return;
832 } 941 }
833 else if (to == pl->count) 942 else if (to == pl->count)
834 { /* pick it up to the inventory */ 943 { /* pick it up to the inventory */
835 /* return if player has already picked it up */ 944 /* return if player has already picked it up */
838 947
839 pl->contr->count = nrof; 948 pl->contr->count = nrof;
840 pick_up (pl, op); 949 pick_up (pl, op);
841 return; 950 return;
842 } 951 }
952
843 env = esrv_get_ob_from_count (pl, to); 953 env = esrv_get_ob_from_count (pl, to);
844 if (!env) 954 if (!env)
845 { 955 {
846 LOG (llevDebug, "Player '%s' tried to move object to the unknown location (%d)\n", &pl->name, to); 956 LOG (llevDebug, "Player '%s' tried to move object to the unknown location (%d)\n", &pl->name, to);
847 return; 957 return;
848 } 958 }
959
849 /* put_object_in_sack presumes that necessary sanity checking 960 /* put_object_in_sack presumes that necessary sanity checking
850 * has already been done (eg, it can be picked up and fits in 961 * 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 962 * 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. 963 * an make sure env is in fact a container for that matter.
853 */ 964 */
854 if (env->type == CONTAINER && can_pick (pl, op) && sack_can_hold (pl, env, op, nrof)) 965 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); 966 put_object_in_sack (pl, env, op, nrof);
857 }
858} 967}
968

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines