[CF-Devel] Bug in stealing code
crossfire-devel at archives.real-time.com
crossfire-devel at archives.real-time.com
Sat Jun 5 11:17:04 CDT 2004
Mark Wedel wrote:
>
It might actually make more sense to treat the weight like any
>
of the other stats (at least player weight), store the last
>
value we sent, and send again if different instead of having
>
these explicit calls.
Here is a diff that should do this.
I declared the function pay_from_container() as "static" since it
is called from nowhere else. In addition I removed the parameter
"object *op" since it is unused.
The use of the magic value "last_weight==(uint32)-1" was necessary
to delay sending "upditem" commands until the player object has
been sent ("player" and "item" commands).
To check (and document) implicit assumptions, I use assert()
statements. Since these statements are basically not used
elsewhere, I'm not sure if I should remove these statements.
-------------- next part --------------
Index: common/item.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/common/item.c,v
retrieving revision 1.44
diff -w -c -5 -r1.44 item.c
*** common/item.c 4 May 2004 07:14:53 -0000 1.44
--- common/item.c 5 Jun 2004 16:01:56 -0000
***************
*** 235,252 ****
return buf;
}
/*
* query_weight(object) returns a character pointer to a static buffer
* containing the text-representation of the weight of the given object.
* The buffer will be overwritten by the next call to query_weight().
*/
char *query_weight(object *op) {
static char buf[10];
! int i=op->nrof?op->nrof*op->weight:op->weight+op->carrying;
if(op->weight<0)
return " ";
if(i%1000)
sprintf(buf,"%6.1f",i/1000.0);
--- 235,260 ----
return buf;
}
/*
+ * get_weight(object) returns the weight of the given object.
+ */
+ sint32 get_weight(const object *op) {
+ return op->nrof ? op->weight : op->weight+op->carrying;
+ }
+
+
+ /*
* query_weight(object) returns a character pointer to a static buffer
* containing the text-representation of the weight of the given object.
* The buffer will be overwritten by the next call to query_weight().
*/
char *query_weight(object *op) {
static char buf[10];
! sint32 i=op->nrof?op->nrof*op->weight:op->weight+op->carrying;
if(op->weight<0)
return " ";
if(i%1000)
sprintf(buf,"%6.1f",i/1000.0);
Index: common/object.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/common/object.c,v
retrieving revision 1.87
diff -w -c -5 -r1.87 object.c
*** common/object.c 18 May 2004 16:11:52 -0000 1.87
--- common/object.c 5 Jun 2004 16:01:56 -0000
***************
*** 1641,1658 ****
if (i < op->nrof) {
sub_weight (op->env, op->weight * i);
op->nrof -= i;
if (tmp) {
(*esrv_send_item_func) (tmp, op);
- (*esrv_update_item_func) (UPD_WEIGHT, tmp, tmp);
}
} else {
remove_ob (op);
op->nrof = 0;
if (tmp) {
(*esrv_del_item_func) (tmp->contr, op->count);
- (*esrv_update_item_func) (UPD_WEIGHT, tmp, tmp);
}
}
}
else
{
--- 1641,1656 ----
Index: include/libproto.h
===================================================================
RCS file: /cvsroot/crossfire/crossfire/include/libproto.h,v
retrieving revision 1.56
diff -w -c -5 -r1.56 libproto.h
*** include/libproto.h 28 Apr 2004 22:04:09 -0000 1.56
--- include/libproto.h 5 Jun 2004 16:01:56 -0000
***************
*** 135,144 ****
--- 135,145 ----
extern void init_attackmess(void);
/* item.c */
extern int get_power_from_ench(int ench);
extern int calc_item_power(object *op, int flag);
extern char *describe_resistance(object *op, int newline);
+ extern sint32 get_weight(const object *op);
extern char *query_weight(object *op);
extern char *get_levelnumber(int i);
extern char *get_number(int i);
extern char *ring_desc(object *op);
extern char *query_short_name(object *op);
Index: include/player.h
===================================================================
RCS file: /cvsroot/crossfire/crossfire/include/player.h,v
retrieving revision 1.35
diff -w -c -5 -r1.35 player.h
*** include/player.h 16 Feb 2004 18:05:32 -0000 1.35
--- include/player.h 5 Jun 2004 16:01:56 -0000
***************
*** 135,144 ****
--- 135,145 ----
sint64 last_skill_exp[NUM_SKILLS]; /* shadow register. if != exp. obj update client */
float weapon_sp; /* Penalties to speed when fighting w speed >ws/10*/
float last_weapon_sp; /* if diff than weapon_sp, update client */
uint16 last_flags; /* fire/run on flags for last tick */
+ uint32 last_weight; /* Last weight as sent to client; (uint32)-1 means do not send weight */
uint32 last_weight_limit; /* Last weight limit transmitted to client */
living orig_stats; /* Permanent real stats of player */
living last_stats; /* Last stats as sent to client */
float last_speed; /* Last speed as sent to client */
sint16 last_resist[NROFATTACKS]; /* last resist values sent to client */
Index: include/sproto.h
===================================================================
RCS file: /cvsroot/crossfire/crossfire/include/sproto.h,v
retrieving revision 1.106
diff -w -c -5 -r1.106 sproto.h
*** include/sproto.h 24 May 2004 21:00:16 -0000 1.106
--- include/sproto.h 5 Jun 2004 16:01:56 -0000
***************
*** 626,636 ****
char *cost_string_from_value(uint64 cost);
char *query_cost_string(object *tmp, object *who, int flag);
uint64 query_money(object *op);
int pay_for_amount(int to_pay, object *pl);
int pay_for_item(object *op, object *pl);
- uint64 pay_from_container(object *op, object *pouch, int to_pay);
int get_payment(object *pl, object *op);
void sell_item(object *op, object *pl);
void shop_listing(object *op);
/* skills.c */
int steal(object *op, int dir, object *skill);
--- 626,635 ----
Index: server/attack.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/server/attack.c,v
retrieving revision 1.98
diff -w -c -5 -r1.98 attack.c
*** server/attack.c 4 May 2004 07:14:53 -0000 1.98
--- server/attack.c 5 Jun 2004 16:01:56 -0000
***************
*** 190,200 ****
if (op->env) {
object *tmp= is_player_inv(op->env);
if (tmp) {
esrv_del_item(tmp->contr, op->count);
- esrv_update_item(UPD_WEIGHT, tmp, tmp);
}
}
if ( ! QUERY_FLAG (op, FLAG_REMOVED))
remove_ob(op);
free_object(op);
--- 190,199 ----
Index: server/c_object.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/server/c_object.c,v
retrieving revision 1.57
diff -w -c -5 -r1.57 c_object.c
*** server/c_object.c 26 Apr 2004 05:07:52 -0000 1.57
--- server/c_object.c 5 Jun 2004 16:01:57 -0000
***************
*** 629,642 ****
*/
if(pl->type!=PLAYER) return;
esrv_send_item (pl, tmp);
/* These are needed to update the weight for the container we
! * are putting the object in, and the players weight, if different.
*/
esrv_update_item (UPD_WEIGHT, pl, op);
! if (op!=pl) esrv_send_item (pl, pl);
/* Update the container the object was in */
if (env && env!=pl && env!=op) esrv_update_item (UPD_WEIGHT, pl, env);
}
--- 629,644 ----
*/
if(pl->type!=PLAYER) return;
esrv_send_item (pl, tmp);
/* These are needed to update the weight for the container we
! * are putting the object in.
*/
+ if (op!=pl) {
esrv_update_item (UPD_WEIGHT, pl, op);
! esrv_send_item (pl, pl);
! }
/* Update the container the object was in */
if (env && env!=pl && env!=op) esrv_update_item (UPD_WEIGHT, pl, env);
}
***************
*** 891,903 ****
*/
if (tmp2 != tmp)
esrv_del_item (op->contr, tmp_tag);
esrv_send_item (op, tmp2);
! /* update the sacks and players weight */
esrv_update_item (UPD_WEIGHT, op, sack);
- esrv_update_item (UPD_WEIGHT, op, op);
}
/*
* This function was part of drop, now is own function.
* Player 'op' tries to drop object 'tmp', if tmp is non zero, then
--- 893,904 ----
*/
if (tmp2 != tmp)
esrv_del_item (op->contr, tmp_tag);
esrv_send_item (op, tmp2);
! /* update the sacks weight */
esrv_update_item (UPD_WEIGHT, op, sack);
}
/*
* This function was part of drop, now is own function.
* Player 'op' tries to drop object 'tmp', if tmp is non zero, then
Index: server/login.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/server/login.c,v
retrieving revision 1.46
diff -w -c -5 -r1.46 login.c
*** server/login.c 12 Mar 2004 19:04:15 -0000 1.46
--- server/login.c 5 Jun 2004 16:01:57 -0000
***************
*** 700,709 ****
--- 700,712 ----
* the data isn't needed.
*/
esrv_new_player(op->contr,op->weight+op->carrying);
esrv_send_inventory(op, op);
+ op->contr->last_weight = 0; /* set to incorrect weight, so esrv_update_item will send correct value */
+ esrv_update_item(UPD_WEIGHT, op, op);
+
CLEAR_FLAG(op, FLAG_FRIENDLY);
/* can_use_shield is a new flag. However, the can_use.. seems to largely come
* from the class, and not race. I don't see any way to get the class information
* to then update this. I don't think this will actually break anything - anyone
Index: server/player.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/server/player.c,v
retrieving revision 1.150
diff -w -c -5 -r1.150 player.c
*** server/player.c 16 Apr 2004 06:23:44 -0000 1.150
--- server/player.c 5 Jun 2004 16:01:57 -0000
***************
*** 204,213 ****
--- 204,214 ----
}
for (i=0; i < NROFATTACKS; i++) {
p->last_resist[i] = -1;
}
p->last_stats.exp = -1;
+ p->last_weight = (uint32)-1;
p->socket.update_look=0;
p->socket.look_position=0;
return p;
}
***************
*** 2828,2838 ****
for (pl = first_player; pl != NULL; pl = pl->next) {
int old = pl->ob->carrying, sum = sum_weight(pl->ob);
if(old == sum)
continue;
fix_player(pl->ob);
- esrv_update_item(UPD_WEIGHT, pl->ob, pl->ob);
LOG(llevDebug,"Fixed inventory in %s (%d -> %d)\n",
pl->ob->name, old, sum);
}
}
--- 2829,2838 ----
Index: server/shop.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/server/shop.c,v
retrieving revision 1.30
diff -w -c -5 -r1.30 shop.c
*** server/shop.c 6 May 2004 07:04:23 -0000 1.30
--- server/shop.c 5 Jun 2004 16:01:57 -0000
***************
*** 24,43 ****
--- 24,47 ----
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The authors can be reached via e-mail at
crossfire-devel at real-time.com
*/
+ #include <assert.h>
#include <global.h>
#include <spells.h>
#include <skills.h>
#include <living.h>
#include <newclient.h>
#ifndef __CEXTRACT__
#include <sproto.h>
#endif
+ static uint64 pay_from_container(object *pouch, uint64 to_pay);
+
+
#define NUM_COINS 3 /* number of coin types */
static char *coins[] = {"platinacoin", "goldcoin", "silvercoin", NULL};
/* Added F_TRUE flag to define.h to mean that the price should not
* be adjusted by players charisma. With F_TRUE, it returns the amount
***************
*** 333,349 ****
object *pouch;
if (to_pay==0) return 1;
if (to_pay > query_money(pl)) return 0;
! to_pay = pay_from_container(NULL, pl, to_pay);
for (pouch=pl->inv; (pouch!=NULL) && (to_pay>0); pouch=pouch->below) {
if (pouch->type == CONTAINER
&& QUERY_FLAG(pouch, FLAG_APPLIED)
&& (pouch->race == NULL || strstr(pouch->race, "gold"))) {
! to_pay = pay_from_container(NULL, pouch, to_pay);
}
}
fix_player(pl);
return 1;
}
--- 337,353 ----
object *pouch;
if (to_pay==0) return 1;
if (to_pay > query_money(pl)) return 0;
! to_pay = pay_from_container(pl, to_pay);
for (pouch=pl->inv; (pouch!=NULL) && (to_pay>0); pouch=pouch->below) {
if (pouch->type == CONTAINER
&& QUERY_FLAG(pouch, FLAG_APPLIED)
&& (pouch->race == NULL || strstr(pouch->race, "gold"))) {
! to_pay = pay_from_container(pouch, to_pay);
}
}
fix_player(pl);
return 1;
}
***************
*** 368,384 ****
saved_money = query_cost(op,pl,F_BUY | F_NO_BARGAIN) - to_pay;
if (saved_money > 0)
change_exp(pl,saved_money,"bargaining",SK_EXP_NONE);
! to_pay = pay_from_container(op, pl, to_pay);
for (pouch=pl->inv; (pouch!=NULL) && (to_pay>0); pouch=pouch->below) {
if (pouch->type == CONTAINER
&& QUERY_FLAG(pouch, FLAG_APPLIED)
&& (pouch->race == NULL || strstr(pouch->race, "gold"))) {
! to_pay = pay_from_container(op, pouch, to_pay);
}
}
if (settings.real_wiz == FALSE && QUERY_FLAG(pl, FLAG_WAS_WIZ))
SET_FLAG(op, FLAG_WAS_WIZ);
fix_player(pl);
--- 372,388 ----
saved_money = query_cost(op,pl,F_BUY | F_NO_BARGAIN) - to_pay;
if (saved_money > 0)
change_exp(pl,saved_money,"bargaining",SK_EXP_NONE);
! to_pay = pay_from_container(pl, to_pay);
for (pouch=pl->inv; (pouch!=NULL) && (to_pay>0); pouch=pouch->below) {
if (pouch->type == CONTAINER
&& QUERY_FLAG(pouch, FLAG_APPLIED)
&& (pouch->race == NULL || strstr(pouch->race, "gold"))) {
! to_pay = pay_from_container(pouch, to_pay);
}
}
if (settings.real_wiz == FALSE && QUERY_FLAG(pl, FLAG_WAS_WIZ))
SET_FLAG(op, FLAG_WAS_WIZ);
fix_player(pl);
***************
*** 391,403 ****
* with weight not be subtracted properly. We now remove and
* insert the coin objects - this should update the weight
* appropriately
*
* DAMN: This function is used for the player, then for any active
! * containers that can hold money, until the op is paid for.
*/
! uint64 pay_from_container(object *op, object *pouch, int to_pay) {
int count, i;
sint64 remain;
object *tmp, *coin_objs[NUM_COINS], *next;
archetype *at;
object *who;
--- 395,411 ----
* with weight not be subtracted properly. We now remove and
* insert the coin objects - this should update the weight
* appropriately
*
* DAMN: This function is used for the player, then for any active
! * containers that can hold money.
! *
! * pouch is the container (pouch or player) to remove the coins from.
! * to_pay is the required amount.
! * returns the amount still missing after using "pouch".
*/
! static uint64 pay_from_container(object *pouch, uint64 to_pay) {
int count, i;
sint64 remain;
object *tmp, *coin_objs[NUM_COINS], *next;
archetype *at;
object *who;
***************
*** 475,490 ****
}
for (i=0; i<NUM_COINS; i++) {
if (coin_objs[i]->nrof) {
object *tmp = insert_ob_in_ob(coin_objs[i], pouch);
for (who = pouch; who && who->type!=PLAYER && who->env!=NULL; who=who->env) ;
esrv_send_item(who, tmp);
esrv_send_item (who, pouch);
! esrv_update_item (UPD_WEIGHT, who, pouch);
if (pouch->type != PLAYER) {
esrv_send_item (who, who);
- esrv_update_item (UPD_WEIGHT, who, who);
}
} else {
free_object(coin_objs[i]);
}
}
--- 483,498 ----
}
for (i=0; i<NUM_COINS; i++) {
if (coin_objs[i]->nrof) {
object *tmp = insert_ob_in_ob(coin_objs[i], pouch);
for (who = pouch; who && who->type!=PLAYER && who->env!=NULL; who=who->env) ;
+ assert(who != NULL && who->type == PLAYER);
esrv_send_item(who, tmp);
esrv_send_item (who, pouch);
! if(who != pouch) esrv_update_item (UPD_WEIGHT, who, pouch);
if (pouch->type != PLAYER) {
esrv_send_item (who, who);
}
} else {
free_object(coin_objs[i]);
}
}
***************
*** 611,621 ****
tmp = insert_ob_in_ob(tmp, pouch);
esrv_send_item (pl, tmp);
esrv_send_item (pl, pouch);
esrv_update_item (UPD_WEIGHT, pl, pouch);
esrv_send_item (pl, pl);
- esrv_update_item (UPD_WEIGHT, pl, pl);
}
}
}
if (i/at->clone.value > 0) {
tmp = get_object();
--- 619,628 ----
***************
*** 623,633 ****
tmp->nrof = i/tmp->value;
i -= (uint64)tmp->nrof * (uint64)tmp->value;
tmp = insert_ob_in_ob(tmp, pl);
esrv_send_item (pl, tmp);
esrv_send_item (pl, pl);
- esrv_update_item (UPD_WEIGHT, pl, pl);
}
}
}
if (i!=0)
--- 630,639 ----
Index: socket/item.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/socket/item.c,v
retrieving revision 1.28
diff -w -c -5 -r1.28 item.c
*** socket/item.c 11 Feb 2004 08:09:29 -0000 1.28
--- socket/item.c 5 Jun 2004 16:01:57 -0000
***************
*** 52,64 ****
*
* Functions related to sending object data to the client.
*
******************************************************************************/
- /** This is more or less stolen from the query_weight function. */
- #define WEIGHT(op) (op->nrof?op->weight:op->weight+op->carrying)
-
/**
* Adds string to socklist.
*
* This is a simple function that we use a lot here. It basically
* adds the specified buffer into the socklist, but prepends a
--- 52,61 ----
***************
*** 225,235 ****
!pl->contr->socket.anims_sent[tmp->animation_id])
esrv_send_animation(&pl->contr->socket, tmp->animation_id);
SockList_AddInt(&sl, tmp->count);
SockList_AddInt(&sl, flags);
! SockList_AddInt(&sl, QUERY_FLAG(tmp, FLAG_NO_PICK) ? -1 : WEIGHT(tmp));
SockList_AddInt(&sl, tmp->face->number);
if (!tmp->custom_name) {
strncpy(item_n,query_base_name(tmp, 0),127);
item_n[127]=0;
--- 222,232 ----
!pl->contr->socket.anims_sent[tmp->animation_id])
esrv_send_animation(&pl->contr->socket, tmp->animation_id);
SockList_AddInt(&sl, tmp->count);
SockList_AddInt(&sl, flags);
! SockList_AddInt(&sl, QUERY_FLAG(tmp, FLAG_NO_PICK) ? -1 : get_weight(tmp));
SockList_AddInt(&sl, tmp->face->number);
if (!tmp->custom_name) {
strncpy(item_n,query_base_name(tmp, 0),127);
item_n[127]=0;
***************
*** 315,325 ****
if (QUERY_FLAG(tmp,FLAG_ANIMATE) &&
!pl->contr->socket.anims_sent[tmp->animation_id])
esrv_send_animation(&pl->contr->socket, tmp->animation_id);
SockList_AddInt(&sl, tmp->count);
SockList_AddInt(&sl, flags);
! SockList_AddInt(&sl, QUERY_FLAG(tmp, FLAG_NO_PICK) ? -1 : WEIGHT(tmp));
SockList_AddInt(&sl, tmp->face->number);
if (!tmp->custom_name) {
strncpy(item_n,query_base_name(tmp, 0),127);
item_n[127]=0;
--- 312,322 ----
if (QUERY_FLAG(tmp,FLAG_ANIMATE) &&
!pl->contr->socket.anims_sent[tmp->animation_id])
esrv_send_animation(&pl->contr->socket, tmp->animation_id);
SockList_AddInt(&sl, tmp->count);
SockList_AddInt(&sl, flags);
! SockList_AddInt(&sl, QUERY_FLAG(tmp, FLAG_NO_PICK) ? -1 : get_weight(tmp));
SockList_AddInt(&sl, tmp->face->number);
if (!tmp->custom_name) {
strncpy(item_n,query_base_name(tmp, 0),127);
item_n[127]=0;
***************
*** 415,426 ****
SockList_AddInt(&sl, op->env? op->env->count:0);
if (flags & UPD_FLAGS)
SockList_AddInt(&sl, query_flags(op));
! if (flags & UPD_WEIGHT)
! SockList_AddInt(&sl, WEIGHT(op));
if (flags & UPD_FACE) {
if (!pl->contr->socket.faces_sent[op->face->number])
esrv_send_face(&pl->contr->socket, op->face->number,0);
SockList_AddInt(&sl, op->face->number);
--- 412,428 ----
SockList_AddInt(&sl, op->env? op->env->count:0);
if (flags & UPD_FLAGS)
SockList_AddInt(&sl, query_flags(op));
! if (flags & UPD_WEIGHT) {
! sint32 weight = get_weight(op);
! SockList_AddInt(&sl, weight);
! if (pl == op) {
! op->contr->last_weight = weight;
! }
! }
if (flags & UPD_FACE) {
if (!pl->contr->socket.faces_sent[op->face->number])
esrv_send_face(&pl->contr->socket, op->face->number,0);
SockList_AddInt(&sl, op->face->number);
***************
*** 508,518 ****
!pl->contr->socket.anims_sent[op->animation_id])
esrv_send_animation(&pl->contr->socket, op->animation_id);
SockList_AddInt(&sl, op->count);
SockList_AddInt(&sl, query_flags(op));
! SockList_AddInt(&sl, WEIGHT(op));
SockList_AddInt(&sl, op->face->number);
if(!op->custom_name) {
strncpy(item_n,query_base_name(op, 0),127);
item_n[127]=0;
--- 510,520 ----
!pl->contr->socket.anims_sent[op->animation_id])
esrv_send_animation(&pl->contr->socket, op->animation_id);
SockList_AddInt(&sl, op->count);
SockList_AddInt(&sl, query_flags(op));
! SockList_AddInt(&sl, get_weight(op));
SockList_AddInt(&sl, op->face->number);
if(!op->custom_name) {
strncpy(item_n,query_base_name(op, 0),127);
item_n[127]=0;
Index: socket/loop.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/socket/loop.c,v
retrieving revision 1.26
diff -w -c -5 -r1.26 loop.c
*** socket/loop.c 2 Dec 2003 18:51:44 -0000 1.26
--- socket/loop.c 5 Jun 2004 16:01:57 -0000
***************
*** 37,46 ****
--- 37,47 ----
* maintenance (checking for lost connections and if data has arrived.)
* The reading of data is handled in ericserver.c
*/
+ #include <assert.h>
#include <global.h>
#ifndef __CEXTRACT__
#include <sproto.h>
#include <sockproto.h>
#endif
***************
*** 656,665 ****
--- 657,670 ----
/* Update the players stats once per tick. More efficient than
* sending them whenever they change, and probably just as useful
*/
esrv_update_stats(pl);
+ if (pl->last_weight != (uint32)-1 && pl->last_weight != get_weight(pl->ob)) {
+ esrv_update_item(UPD_WEIGHT, pl->ob, pl->ob);
+ assert(pl->last_weight == get_weight(pl->ob));
+ }
if (pl->ob->map && pl->ob->map->in_memory==MAP_IN_MEMORY)
draw_client_map(pl->ob);
if (pl->socket.update_look) esrv_draw_look(pl->ob);
}
}
-------------- next part --------------
_______________________________________________
crossfire-devel mailing list
crossfire-devel at lists.real-time.com
https://mailman.real-time.com/mailman/listinfo/crossfire-devel
More information about the crossfire
mailing list