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.2 by root, Tue Aug 29 07:34:01 2006 UTC vs.
Revision 1.29 by root, Thu Dec 21 23:37:06 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines