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.6 by root, Tue Sep 12 19:20:09 2006 UTC vs.
Revision 1.30 by pippijn, Sat Jan 6 14:42:31 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines