Ver Fonte

Add rewarp_count counter to prevent infinite warp loop.
bugreport:9130 (cpu-usage-goes-to-100)

lighta há 10 anos atrás
pai
commit
ea8ccfc82e
5 ficheiros alterados com 31 adições e 8 exclusões
  1. 3 0
      npc/test/infinite_warp.txt
  2. 16 4
      src/map/npc.c
  3. 7 0
      src/map/pc.c
  4. 1 0
      src/map/pc.h
  5. 4 4
      src/map/skill.c

+ 3 - 0
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

+ 16 - 4
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;

+ 7 - 0
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;
 }
 

+ 1 - 0
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

+ 4 - 4
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;