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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines