From ea8ccfc82e91efb9fc1be3d3397d538d80101c84 Mon Sep 17 00:00:00 2001 From: lighta Date: Fri, 29 Aug 2014 16:05:41 -0400 Subject: [PATCH] Add rewarp_count counter to prevent infinite warp loop. bugreport:9130 (cpu-usage-goes-to-100) --- npc/test/infinite_warp.txt | 3 +++ src/map/npc.c | 20 ++++++++++++++++---- src/map/pc.c | 7 +++++++ src/map/pc.h | 1 + src/map/skill.c | 8 ++++---- 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 npc/test/infinite_warp.txt diff --git a/npc/test/infinite_warp.txt b/npc/test/infinite_warp.txt new file mode 100644 index 0000000000..0e3c381018 --- /dev/null +++ b/npc/test/infinite_warp.txt @@ -0,0 +1,3 @@ +e_tower,74,116,0 warp #inf_warp1 2,2,e_tower,81,108 +e_tower,81,108,0 warp #inf_warp2 2,2,e_tower,75,84 +e_tower,75,84,0 warp #inf_warp3 2,2,e_tower,74,116 diff --git a/src/map/npc.c b/src/map/npc.c index 60847df28d..62db089e28 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -969,6 +969,11 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) case NPCTYPE_WARP: if (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]) || pc_isdead(sd)) break; // hidden or dead chars cannot use warps + if(sd->count_rewarp > 3){ + ShowWarning("Prevent infinite warping loop, please fix script\n"); + sd->count_rewarp=0; + break; + } pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,CLR_OUTSIGHT); break; case NPCTYPE_SCRIPT: @@ -1068,10 +1073,17 @@ int npc_touch_areanpc2(struct mob_data *md) return 0; } -//Checks if there are any NPC on-touch objects on the given range. -//Flag determines the type of object to check for: -//&1: NPC Warps -//&2: NPCs with on-touch events. +/** + * Checks if there are any NPC on-touch objects on the given range. + * @param flag : Flag determines the type of object to check for + * &1: NPC Warps + * &2: NPCs with on-touch events. + * @param m : mapindex + * @param x : x coord + * @param y : y coord + * @param range : range to check + * @return 0: no npc on target cells, x: npc_id + */ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) { int i; diff --git a/src/map/pc.c b/src/map/pc.c index 364d6a7f72..a62e26c356 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1211,6 +1211,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->num_quests = 0; sd->avail_quests = 0; sd->save_quest = false; + sd->count_rewarp = 0; //warp player if ((i=pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != 0) { @@ -5299,6 +5300,12 @@ char pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int } pc_cell_basilica(sd); + + //check if we gonna be rewarped [lighta] + if(npc_check_areanpc(1,m,x,y,1)){ + sd->count_rewarp++; + } + return 0; } diff --git a/src/map/pc.h b/src/map/pc.h index 0e7ef54bd4..e294c1cb8e 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -245,6 +245,7 @@ struct map_session_data { unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex] int group_id, group_pos, group_level; unsigned int permissions;/* group permissions */ + int count_rewarp; //count how many time we being rewarped int langtype; uint32 packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18 diff --git a/src/map/skill.c b/src/map/skill.c index 8654ff19be..2881f5f3dc 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -17719,17 +17719,17 @@ short skill_can_produce_mix (struct map_session_data *sd, unsigned short nameid, // Check on player's inventory for (j = 0; j < MAX_PRODUCE_RESOURCE; j++) { - unsigned short nameid; - if ((nameid = skill_produce_db[i].mat_id[j]) == 0 ) + unsigned short nameid_produce; + if ((nameid_produce = skill_produce_db[i].mat_id[j]) == 0 ) continue; if (skill_produce_db[i].mat_amount[j] == 0) { - if (pc_search_inventory(sd,nameid) < 0) + if (pc_search_inventory(sd,nameid_produce) < 0) return 0; } else { unsigned short idx, amt; for (idx = 0, amt = 0; idx < MAX_INVENTORY; idx++) - if (sd->status.inventory[idx].nameid == nameid) + if (sd->status.inventory[idx].nameid == nameid_produce) amt += sd->status.inventory[idx].amount; if (amt < qty*skill_produce_db[i].mat_amount[j]) return 0;