ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.c
(Generate patch)

Comparing deliantra/server/common/object.c (file contents):
Revision 1.1.1.1 by root, Fri Feb 3 07:11:38 2006 UTC vs.
Revision 1.5 by root, Mon May 29 15:28:24 2006 UTC

1/* 1/*
2 * static char *rcsid_object_c = 2 * static char *rcsid_object_c =
3 * "$Id: object.c,v 1.1.1.1 2006/02/03 07:11:38 root Exp $"; 3 * "$Id: object.c,v 1.5 2006/05/29 15:28:24 root Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
52 52
53object *objects; /* Pointer to the list of used objects */ 53object *objects; /* Pointer to the list of used objects */
54object *free_objects; /* Pointer to the list of unused objects */ 54object *free_objects; /* Pointer to the list of unused objects */
55object *active_objects; /* List of active objects that need to be processed */ 55object *active_objects; /* List of active objects that need to be processed */
56 56
57void (*object_free_callback)(object *ob);
57 58
58short freearr_x[SIZEOFFREE]= 59short freearr_x[SIZEOFFREE]=
59 {0,0,1,1,1,0,-1,-1,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1, 60 {0,0,1,1,1,0,-1,-1,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1,
60 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1}; 61 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1};
61short freearr_y[SIZEOFFREE]= 62short freearr_y[SIZEOFFREE]=
68 0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8, 69 0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8,
69 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8}; 70 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8};
70 71
71 72
72/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 73/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
73static int compare_ob_value_lists_one(object * wants, object * has) { 74static int compare_ob_value_lists_one(const object * wants, const object * has) {
74 key_value * wants_field; 75 key_value * wants_field;
75 76
76 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both 77 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
77 * objects with lists are rare, and lists stay short. If not, use a 78 * objects with lists are rare, and lists stay short. If not, use a
78 * different structure or at least keep the lists sorted... 79 * different structure or at least keep the lists sorted...
102 /* If we get here, every field in wants has a matching field in has. */ 103 /* If we get here, every field in wants has a matching field in has. */
103 return TRUE; 104 return TRUE;
104} 105}
105 106
106/* Returns TRUE if ob1 has the same key_values as ob2. */ 107/* Returns TRUE if ob1 has the same key_values as ob2. */
107static int compare_ob_value_lists(object * ob1, object * ob2) { 108static int compare_ob_value_lists(const object * ob1, const object * ob2) {
108 /* However, there may be fields in has which aren't partnered in wants, 109 /* However, there may be fields in has which aren't partnered in wants,
109 * so we need to run the comparison *twice*. :( 110 * so we need to run the comparison *twice*. :(
110 */ 111 */
111 return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1); 112 return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1);
112} 113}
197 (ob1->materialname != ob2->materialname) || 198 (ob1->materialname != ob2->materialname) ||
198 (ob1->lore != ob2->lore) || 199 (ob1->lore != ob2->lore) ||
199 (ob1->subtype != ob2->subtype) || 200 (ob1->subtype != ob2->subtype) ||
200 (ob1->move_type != ob2->move_type) || 201 (ob1->move_type != ob2->move_type) ||
201 (ob1->move_block != ob2->move_block) || 202 (ob1->move_block != ob2->move_block) ||
203 (ob1->move_allow != ob2->move_allow) ||
202 (ob1->move_on != ob2->move_on) || 204 (ob1->move_on != ob2->move_on) ||
203 (ob1->move_off != ob2->move_off) || 205 (ob1->move_off != ob2->move_off) ||
204 (ob1->move_slow != ob2->move_slow) || 206 (ob1->move_slow != ob2->move_slow) ||
205 (ob1->move_slow_penalty != ob2->move_slow_penalty) 207 (ob1->move_slow_penalty != ob2->move_slow_penalty)
206 ) 208 )
211 * some items equipped, and we don't want those to merge. 213 * some items equipped, and we don't want those to merge.
212 */ 214 */
213 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED)) 215 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))
214 return 0; 216 return 0;
215 217
218 switch (ob1->type) {
219 case SCROLL:
220 if (ob1->level != ob2->level) return 0;
221 break;
222
223 }
216 if (ob1->key_values != NULL || ob2->key_values != NULL) { 224 if (ob1->key_values != NULL || ob2->key_values != NULL) {
217 /* At least one of these has key_values. */ 225 /* At least one of these has key_values. */
218 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) { 226 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
219 /* One has fields, but the other one doesn't. */ 227 /* One has fields, but the other one doesn't. */
220 return 0; 228 return 0;
221 } else {
222 return compare_ob_value_lists(ob1, ob2); 229 } else if (!compare_ob_value_lists(ob1, ob2)) {
230 return 0;
223 } 231 }
224 } 232 }
225 233
226 switch (ob1->type) {
227 case SCROLL:
228 if (ob1->level != ob2->level) return 0;
229 break;
230
231 }
232 /* Everything passes, must be OK. */ 234 /* Everything passes, must be OK. */
233 return 1; 235 return 1;
234} 236}
235 237
236/* 238/*
384 * get_nearest_part(multi-object, object 2) returns the part of the 386 * get_nearest_part(multi-object, object 2) returns the part of the
385 * multi-object 1 which is closest to the second object. 387 * multi-object 1 which is closest to the second object.
386 * If it's not a multi-object, it is returned. 388 * If it's not a multi-object, it is returned.
387 */ 389 */
388 390
389object *get_nearest_part(object *op,object *pl) { 391object *get_nearest_part(object *op, const object *pl) {
390 object *tmp,*closest; 392 object *tmp,*closest;
391 int last_dist,i; 393 int last_dist,i;
392 if(op->more==NULL) 394 if(op->more==NULL)
393 return op; 395 return op;
394 for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more) 396 for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more)
413 * Returns the first object which has a name equal to the argument. 415 * Returns the first object which has a name equal to the argument.
414 * Used only by the patch command, but not all that useful. 416 * Used only by the patch command, but not all that useful.
415 * Enables features like "patch <name-of-other-player> food 999" 417 * Enables features like "patch <name-of-other-player> food 999"
416 */ 418 */
417 419
418object *find_object_name(char *str) { 420object *find_object_name(const char *str) {
419 const char *name=add_string(str); 421 const char *name=add_string(str);
420 object *op; 422 object *op;
421 for(op=objects;op!=NULL;op=op->next) 423 for(op=objects;op!=NULL;op=op->next)
422 if(op->name==name) 424 if(op->name==name)
423 break; 425 break;
1018 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE)) 1020 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE))
1019 update_now=1; 1021 update_now=1;
1020 1022
1021 if ((move_on | op->move_on) != move_on) update_now=1; 1023 if ((move_on | op->move_on) != move_on) update_now=1;
1022 if ((move_off | op->move_off) != move_off) update_now=1; 1024 if ((move_off | op->move_off) != move_off) update_now=1;
1025 /* This isn't perfect, but I don't expect a lot of objects to
1026 * to have move_allow right now.
1027 */
1023 if ((move_block | op->move_block) != move_block) update_now=1; 1028 if (((move_block | op->move_block) & ~op->move_allow) != move_block)
1029 update_now=1;
1024 if ((move_slow | op->move_slow) != move_slow) update_now=1; 1030 if ((move_slow | op->move_slow) != move_slow) update_now=1;
1025 } 1031 }
1026 /* if the object is being removed, we can't make intelligent 1032 /* if the object is being removed, we can't make intelligent
1027 * decisions, because remove_ob can't really pass the object 1033 * decisions, because remove_ob can't really pass the object
1028 * that is being removed. 1034 * that is being removed.
1060void free_object(object *ob) { 1066void free_object(object *ob) {
1061 free_object2(ob, 0); 1067 free_object2(ob, 0);
1062} 1068}
1063void free_object2(object *ob, int free_inventory) { 1069void free_object2(object *ob, int free_inventory) {
1064 object *tmp,*op; 1070 object *tmp,*op;
1071
1072 if (object_free_callback)
1073 object_free_callback (ob);
1065 1074
1066 if (!QUERY_FLAG(ob,FLAG_REMOVED)) { 1075 if (!QUERY_FLAG(ob,FLAG_REMOVED)) {
1067 LOG(llevDebug,"Free object called with non removed object\n"); 1076 LOG(llevDebug,"Free object called with non removed object\n");
1068 dump_object(ob); 1077 dump_object(ob);
1069#ifdef MANY_CORES 1078#ifdef MANY_CORES
1507 if(op->more!=NULL) { 1516 if(op->more!=NULL) {
1508 /* The part may be on a different map. */ 1517 /* The part may be on a different map. */
1509 1518
1510 object *more = op->more; 1519 object *more = op->more;
1511 1520
1521 /* We really need the caller to normalize coordinates - if
1522 * we set the map, that doesn't work if the location is within
1523 * a map and this is straddling an edge. So only if coordinate
1524 * is clear wrong do we normalize it.
1525 */
1526 if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
1512 /* Debugging information so you can see the last coordinates this object had */ 1527 /* Debugging information so you can see the last coordinates this object had */
1513 more->ox = more->x; 1528 more->ox = more->x;
1514 more->oy = more->y; 1529 more->oy = more->y;
1515 more->map = get_map_from_coord(m, &more->x, &more->y); 1530 more->map = get_map_from_coord(m, &more->x, &more->y);
1531 } else if (!more->map) {
1532 /* For backwards compatibility - when not dealing with tiled maps,
1533 * more->map should always point to the parent.
1534 */
1535 more->map = m;
1536 }
1516 1537
1517 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) { 1538 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) {
1518 if ( ! op->head) 1539 if ( ! op->head)
1519 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); 1540 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n");
1520 return NULL; 1541 return NULL;
1702 1723
1703/* this function inserts an object in the map, but if it 1724/* this function inserts an object in the map, but if it
1704 * finds an object of its own type, it'll remove that one first. 1725 * finds an object of its own type, it'll remove that one first.
1705 * op is the object to insert it under: supplies x and the map. 1726 * op is the object to insert it under: supplies x and the map.
1706 */ 1727 */
1707void replace_insert_ob_in_map(char *arch_string, object *op) { 1728void replace_insert_ob_in_map(const char *arch_string, object *op) {
1708 object *tmp; 1729 object *tmp;
1709 object *tmp1; 1730 object *tmp1;
1710 1731
1711 /* first search for itself and remove any old instances */ 1732 /* first search for itself and remove any old instances */
1712 1733
2080 * present_arch(arch, map, x, y) searches for any objects with 2101 * present_arch(arch, map, x, y) searches for any objects with
2081 * a matching archetype at the given map and coordinates. 2102 * a matching archetype at the given map and coordinates.
2082 * The first matching object is returned, or NULL if none. 2103 * The first matching object is returned, or NULL if none.
2083 */ 2104 */
2084 2105
2085object *present_arch(archetype *at, mapstruct *m, int x, int y) { 2106object *present_arch(const archetype *at, mapstruct *m, int x, int y) {
2086 object *tmp; 2107 object *tmp;
2087 if(m==NULL || out_of_map(m,x,y)) { 2108 if(m==NULL || out_of_map(m,x,y)) {
2088 LOG(llevError,"Present_arch called outside map.\n"); 2109 LOG(llevError,"Present_arch called outside map.\n");
2089 return NULL; 2110 return NULL;
2090 } 2111 }
2116 * present_in_ob(type, object) searches for any objects with 2137 * present_in_ob(type, object) searches for any objects with
2117 * a matching type variable in the inventory of the given object. 2138 * a matching type variable in the inventory of the given object.
2118 * The first matching object is returned, or NULL if none. 2139 * The first matching object is returned, or NULL if none.
2119 */ 2140 */
2120 2141
2121object *present_in_ob(unsigned char type,object *op) { 2142object *present_in_ob(unsigned char type, const object *op) {
2122 object *tmp; 2143 object *tmp;
2123 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2144 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2124 if(tmp->type==type) 2145 if(tmp->type==type)
2125 return tmp; 2146 return tmp;
2126 return NULL; 2147 return NULL;
2139 * the object name, not the archetype name. this is so that the 2160 * the object name, not the archetype name. this is so that the
2140 * spell code can use one object type (force), but change it's name 2161 * spell code can use one object type (force), but change it's name
2141 * to be unique. 2162 * to be unique.
2142 */ 2163 */
2143 2164
2144object *present_in_ob_by_name(int type, char *str,object *op) { 2165object *present_in_ob_by_name(int type, const char *str, const object *op) {
2145 object *tmp; 2166 object *tmp;
2146 2167
2147 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { 2168 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) {
2148 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) 2169 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name)))
2149 return tmp; 2170 return tmp;
2155 * present_arch_in_ob(archetype, object) searches for any objects with 2176 * present_arch_in_ob(archetype, object) searches for any objects with
2156 * a matching archetype in the inventory of the given object. 2177 * a matching archetype in the inventory of the given object.
2157 * The first matching object is returned, or NULL if none. 2178 * The first matching object is returned, or NULL if none.
2158 */ 2179 */
2159 2180
2160object *present_arch_in_ob(archetype *at, object *op) { 2181object *present_arch_in_ob(const archetype *at, const object *op) {
2161 object *tmp; 2182 object *tmp;
2162 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2183 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2163 if( tmp->arch == at) 2184 if( tmp->arch == at)
2164 return tmp; 2185 return tmp;
2165 return NULL; 2186 return NULL;
2219 * to know if the space in question will block the object. We can't use 2240 * to know if the space in question will block the object. We can't use
2220 * the archetype because that isn't correct if the monster has been 2241 * the archetype because that isn't correct if the monster has been
2221 * customized, changed states, etc. 2242 * customized, changed states, etc.
2222 */ 2243 */
2223 2244
2224int find_free_spot(object *ob, mapstruct *m,int x,int y,int start,int stop) { 2245int find_free_spot(const object *ob, mapstruct *m,int x,int y,int start,int stop) {
2225 int i,index=0, flag; 2246 int i,index=0, flag;
2226 static int altern[SIZEOFFREE]; 2247 static int altern[SIZEOFFREE];
2227 2248
2228 for(i=start;i<stop;i++) { 2249 for(i=start;i<stop;i++) {
2229 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]); 2250 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]);
2250 * find_free_spot(), but it will search max number of squares. 2271 * find_free_spot(), but it will search max number of squares.
2251 * But it will return the first available spot, not a random choice. 2272 * But it will return the first available spot, not a random choice.
2252 * Changed 0.93.2: Have it return -1 if there is no free spot available. 2273 * Changed 0.93.2: Have it return -1 if there is no free spot available.
2253 */ 2274 */
2254 2275
2255int find_first_free_spot(object *ob, mapstruct *m,int x,int y) { 2276int find_first_free_spot(const object *ob, mapstruct *m,int x,int y) {
2256 int i; 2277 int i;
2257 for(i=0;i<SIZEOFFREE;i++) { 2278 for(i=0;i<SIZEOFFREE;i++) {
2258 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) 2279 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]))
2259 return i; 2280 return i;
2260 } 2281 }
2361/* 2382/*
2362 * distance(object 1, object 2) will return the square of the 2383 * distance(object 1, object 2) will return the square of the
2363 * distance between the two given objects. 2384 * distance between the two given objects.
2364 */ 2385 */
2365 2386
2366int distance(object *ob1,object *ob2) { 2387int distance(const object *ob1, const object *ob2) {
2367 int i; 2388 int i;
2368 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ 2389 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+
2369 (ob1->y - ob2->y)*(ob1->y - ob2->y); 2390 (ob1->y - ob2->y)*(ob1->y - ob2->y);
2370 return i; 2391 return i;
2371} 2392}
2536 * core dumps if they do. 2557 * core dumps if they do.
2537 * 2558 *
2538 * Add a check so we can't pick up invisible objects (0.93.8) 2559 * Add a check so we can't pick up invisible objects (0.93.8)
2539 */ 2560 */
2540 2561
2541int can_pick(object *who,object *item) { 2562int can_pick(const object *who, const object *item) {
2542 return /*QUERY_FLAG(who,FLAG_WIZ)||*/ 2563 return /*QUERY_FLAG(who,FLAG_WIZ)||*/
2543 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& 2564 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&&
2544 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && 2565 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible &&
2545 (who->type==PLAYER||item->weight<who->weight/3)); 2566 (who->type==PLAYER||item->weight<who->weight/3));
2546} 2567}
2581 2602
2582 return dst; 2603 return dst;
2583} 2604}
2584 2605
2585/* return true if the object was destroyed, 0 otherwise */ 2606/* return true if the object was destroyed, 0 otherwise */
2586int was_destroyed (object *op, tag_t old_tag) 2607int was_destroyed (const object *op, tag_t old_tag)
2587{ 2608{
2588 /* checking for FLAG_FREED isn't necessary, but makes this function more 2609 /* checking for FLAG_FREED isn't necessary, but makes this function more
2589 * robust */ 2610 * robust */
2590 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); 2611 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED);
2591} 2612}
2595/* load_object on it. I admit it is a highly inefficient way to make things, */ 2616/* load_object on it. I admit it is a highly inefficient way to make things, */
2596/* but it was simple to make and allows reusing the load_object function. */ 2617/* but it was simple to make and allows reusing the load_object function. */
2597/* Remember not to use load_object_str in a time-critical situation. */ 2618/* Remember not to use load_object_str in a time-critical situation. */
2598/* Also remember that multiparts objects are not supported for now. */ 2619/* Also remember that multiparts objects are not supported for now. */
2599 2620
2600object* load_object_str(char *obstr) 2621object* load_object_str(const char *obstr)
2601{ 2622{
2602 object *op; 2623 object *op;
2603 FILE *tempfile; 2624 FILE *tempfile;
2604 char filename[MAX_BUF]; 2625 char filename[MAX_BUF];
2605 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); 2626 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir);
2629 2650
2630/* This returns the first object in who's inventory that 2651/* This returns the first object in who's inventory that
2631 * has the same type and subtype match. 2652 * has the same type and subtype match.
2632 * returns NULL if no match. 2653 * returns NULL if no match.
2633 */ 2654 */
2634object *find_obj_by_type_subtype(object *who, int type, int subtype) 2655object *find_obj_by_type_subtype(const object *who, int type, int subtype)
2635{ 2656{
2636 object *tmp; 2657 object *tmp;
2637 2658
2638 for (tmp=who->inv; tmp; tmp=tmp->below) 2659 for (tmp=who->inv; tmp; tmp=tmp->below)
2639 if (tmp->type == type && tmp->subtype == subtype) return tmp; 2660 if (tmp->type == type && tmp->subtype == subtype) return tmp;
2645 * otherwise return NULL. 2666 * otherwise return NULL.
2646 * 2667 *
2647 * key must be a passed in shared string - otherwise, this won't 2668 * key must be a passed in shared string - otherwise, this won't
2648 * do the desired thing. 2669 * do the desired thing.
2649 */ 2670 */
2650key_value * get_ob_key_link(object * ob, const char * key) { 2671key_value * get_ob_key_link(const object * ob, const char * key) {
2651 key_value * link; 2672 key_value * link;
2652 2673
2653 for (link = ob->key_values; link != NULL; link = link->next) { 2674 for (link = ob->key_values; link != NULL; link = link->next) {
2654 if (link->key == key) { 2675 if (link->key == key) {
2655 return link; 2676 return link;
2664 * 2685 *
2665 * The argument doesn't need to be a shared string. 2686 * The argument doesn't need to be a shared string.
2666 * 2687 *
2667 * The returned string is shared. 2688 * The returned string is shared.
2668 */ 2689 */
2669const char * get_ob_key_value(object * op, const char * const key) { 2690const char * get_ob_key_value(const object * op, const char * const key) {
2670 key_value * link; 2691 key_value * link;
2671 const char * canonical_key; 2692 const char * canonical_key;
2672 2693
2673 canonical_key = find_string(key); 2694 canonical_key = find_string(key);
2674 2695
2704 * Returns TRUE on success. 2725 * Returns TRUE on success.
2705 */ 2726 */
2706int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { 2727int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) {
2707 key_value * field = NULL, *last=NULL; 2728 key_value * field = NULL, *last=NULL;
2708 2729
2709 LOG(llevDebug, "set_ob_value_s: '%s' '%s' %d\n", canonical_key, value, add_key);
2710
2711 for (field=op->key_values; field != NULL; field=field->next) { 2730 for (field=op->key_values; field != NULL; field=field->next) {
2712 if (field->key != canonical_key) { 2731 if (field->key != canonical_key) {
2713 last = field; 2732 last = field;
2714 continue; 2733 continue;
2715 } 2734 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines