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.4 by root, Sun Sep 3 00:18:43 2006 UTC vs.
Revision 1.14 by root, Thu Dec 14 00:23:59 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines