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.3 by root, Tue Aug 29 08:01:38 2006 UTC vs.
Revision 1.31 by root, Mon Jan 8 18:18:36 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines