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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines