Przeglądaj źródła

Little fix for //quest_reload.
NOTE, This commit does NOT fix the following issues:
a) the quests may still ONLY be reloaded if the questname starts with an alpha character (i.e. non-number)
b) npc reloads (respawn-all etc) still cause all NPCs to lose all their quests
c) there is still an issue when removing an NPC from a quest that you reload; namely, if the new version of the quest is removing an NPC from an event (like deleting a QUEST.addTalkId(xxxxx) line), the npc will NOT be removed! That particular NPC will, in fact, still use the old version of the quest!! (this will be fixed in a future update)

This commit DOES fix the following:
a) The players' QuestStates no longer refer to the old scripts. Instead, the new quest scripts are always found correctly from the QuestState
b) If a mobs that are registered by the new version, including both mobs that also existed in the old version and mobs that were newly adde to the script, will properly update their quest references and work as dictated by the new script.
c) The QuestManager class properly keeps track only of the latest quest, using its questName as lookup key.

This has been tested by Emperorc and by myself and worked to the above specs so far. More to come soon...

Fulminus 17 lat temu
rodzic
commit
fc34b47c0f

+ 24 - 47
L2_GameServer_It/java/net/sf/l2j/gameserver/instancemanager/QuestManager.java

@@ -17,10 +17,11 @@
  */
 package net.sf.l2j.gameserver.instancemanager;
 
-import java.util.List;
 import java.util.logging.Logger;
 
-import javolution.util.FastList;
+import java.util.Map;
+import javolution.util.FastMap;
+
 import net.sf.l2j.Config;
 import net.sf.l2j.gameserver.model.quest.Quest;
 import net.sf.l2j.gameserver.model.quest.jython.QuestJython;
@@ -47,7 +48,7 @@ public class QuestManager
 
     // =========================================================
     // Data Field
-    private List<Quest> _quests = new FastList<Quest>();
+    private Map<String, Quest> _quests = new FastMap<String, Quest>();
 
     // =========================================================
     // Constructor
@@ -59,7 +60,9 @@ public class QuestManager
     // Method - Public
     public final boolean reload(String questFolder)
     {
-    	getQuest(questFolder).saveGlobalData();
+    	Quest q = getQuest(questFolder);
+    	if (q!=null)
+    		q.saveGlobalData();
     	return QuestJython.reloadQuest(questFolder);
     }
     
@@ -89,7 +92,7 @@ public class QuestManager
     }
     public final void save()
     {
-    	for(Quest q:_quests)
+    	for(Quest q: getQuests().values())
     		q.saveGlobalData();
     }
 
@@ -97,59 +100,33 @@ public class QuestManager
     // Property - Public
     public final Quest getQuest(String name)
     {
-        int index = getQuestIndex(name);
-        if (index >= 0) return getQuests().get(index);
-        return null;
+        return getQuests().get(name);
     }
 
     public final Quest getQuest(int questId)
     {
-        int index = getQuestIndex(questId);
-        if (index >= 0) return getQuests().get(index);
-        return null;
-    }
-    
-    public final int getQuestIndex(String name)
-    {
-        Quest quest;
-        for (int i = 0; i < getQuests().size(); i++)
-        {
-            quest = getQuests().get(i);
-            if (quest != null && quest.getName().equalsIgnoreCase(name)) return i;
-        }
-        return -1;
-    }
-    
-    public final int getQuestIndex(int questId)
-    {
-        Quest quest;
-        for (int i = 0; i < getQuests().size(); i++)
-        {
-            quest = getQuests().get(i);
-            if (quest != null && quest.getQuestIntId() == questId) return i;
-        }
-        return -1;
+    	for (Quest q: getQuests().values())
+    	{
+    		if (q.getQuestIntId() == questId)
+    			return q;
+    	}
+    	return null;
     }
     
+
     public final void addQuest(Quest newQuest)
     {
-    	for (Quest quest : getQuests())
-        {
-    		if (quest.getName().equalsIgnoreCase(newQuest.getName()))
-    		{
-    			_log.info("Replaced: "+quest.getName()+" with "+newQuest.getName());
-    			getQuests().remove(quest);
-    			getQuests().add(newQuest);
-    			return;
-    		}
-        }
+    	if (getQuests().containsKey(newQuest.getName()))
+			_log.info("Replaced: "+newQuest.getName()+" with a new version");
     	
-    	getQuests().add(newQuest);
+    	// Note: FastMap will replace the old value if the key already exists
+    	// so there is no need to explicitly try to remove the old reference.
+    	getQuests().put(newQuest.getName(), newQuest);
     }
     
-    public final List<Quest> getQuests()
+    public final FastMap<String, Quest> getQuests()
     {
-        if (_quests == null) _quests = new FastList<Quest>();
-        return _quests;
+        if (_quests == null) _quests = new FastMap<String, Quest>();
+        return (FastMap<String, Quest>) _quests;
     }
 }

+ 3 - 2
L2_GameServer_It/java/net/sf/l2j/gameserver/model/actor/instance/L2NpcInstance.java

@@ -1226,7 +1226,9 @@ public class L2NpcInstance extends L2Character
     {
         String content;
         
-        if (player.getWeightPenalty()>=3){	
+        Quest q = QuestManager.getInstance().getQuest(questId);
+
+        if (player.getWeightPenalty()>=3 && q.getQuestIntId() >= 1 && q.getQuestIntId() < 1000 ){	
             player.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_LESS_THAN_80_PERCENT));
             return;
         }
@@ -1244,7 +1246,6 @@ public class L2NpcInstance extends L2Character
         }
         else
         {
-            Quest q = QuestManager.getInstance().getQuest(questId);
             if (q != null) 
             {
                 // check for start point

+ 1 - 1
L2_GameServer_It/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java

@@ -1165,7 +1165,7 @@ public final class L2PcInstance extends L2PlayableInstance
 	 */
 	public void setQuestState(QuestState qs)
 	{
-		_quests.put(qs.getQuest().getName(), qs);
+		_quests.put(qs.getQuestName(), qs);
 	}
 
 

+ 4 - 4
L2_GameServer_It/java/net/sf/l2j/gameserver/model/quest/Quest.java

@@ -608,7 +608,7 @@ public abstract class Quest
             PreparedStatement statement;
             statement = con.prepareStatement("INSERT INTO character_quests (char_id,name,var,value) VALUES (?,?,?,?)");
             statement.setInt   (1, qs.getPlayer().getObjectId());
-            statement.setString(2, qs.getQuest().getName());
+            statement.setString(2, qs.getQuestName());
             statement.setString(3, var);
             statement.setString(4, value);
 	    statement.executeUpdate();
@@ -643,7 +643,7 @@ public abstract class Quest
             statement = con.prepareStatement("UPDATE character_quests SET value=? WHERE char_id=? AND name=? AND var = ?");
             statement.setString(1, value);
             statement.setInt   (2, qs.getPlayer().getObjectId());
-            statement.setString(3, qs.getQuest().getName());
+            statement.setString(3, qs.getQuestName());
             statement.setString(4, var);
 			statement.executeUpdate();
             statement.close();
@@ -667,7 +667,7 @@ public abstract class Quest
             PreparedStatement statement;
             statement = con.prepareStatement("DELETE FROM character_quests WHERE char_id=? AND name=? AND var=?");
             statement.setInt   (1, qs.getPlayer().getObjectId());
-            statement.setString(2, qs.getQuest().getName());
+            statement.setString(2, qs.getQuestName());
             statement.setString(3, var);
 	    statement.executeUpdate();
             statement.close();
@@ -690,7 +690,7 @@ public abstract class Quest
             PreparedStatement statement;
             statement = con.prepareStatement("DELETE FROM character_quests WHERE char_id=? AND name=?");
             statement.setInt   (1, qs.getPlayer().getObjectId());
-            statement.setString(2, qs.getQuest().getName());
+            statement.setString(2, qs.getQuestName());
 			statement.executeUpdate();
             statement.close();
         } catch (Exception e) {

+ 14 - 10
L2_GameServer_It/java/net/sf/l2j/gameserver/model/quest/QuestState.java

@@ -26,6 +26,7 @@ import java.util.logging.Logger;
 import javolution.util.FastList;
 import javolution.util.FastMap;
 import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.instancemanager.QuestManager;
 import net.sf.l2j.gameserver.GameTimeController;
 import net.sf.l2j.gameserver.model.L2Character;
 import net.sf.l2j.gameserver.model.L2DropData;
@@ -50,7 +51,7 @@ public final class QuestState
 	protected static final Logger _log = Logger.getLogger(Quest.class.getName());
 
 	/** Quest associated to the QuestState */
-	private final Quest _quest;
+	private final String _questName;
 
 	/** Player who engaged the quest */
 	private final L2PcInstance _player;
@@ -85,7 +86,7 @@ public final class QuestState
 	 */
     QuestState(Quest quest, L2PcInstance player, State state, boolean completed)
     {
-		_quest = quest;
+    	_questName = quest.getName();
 		_player = player;
 
 		// Save the state of the quest for the player in the player's list of quest onwed
@@ -108,13 +109,17 @@ public final class QuestState
 		}
     }
 
+    public String getQuestName()
+    {
+    	return _questName;
+    }
     /**
      * Return the quest
      * @return Quest
      */
 	public Quest getQuest()
     {
-		return _quest;
+		return QuestManager.getInstance().getQuest(_questName);
 	}
 
 	/**
@@ -306,7 +311,7 @@ public final class QuestState
 	        }
 	        catch (Exception e)
 	        {
-	            _log.finer(getPlayer().getName()+", "+getQuest().getName()+" cond ["+val+"] is not an integer.  Value stored, but no packet was sent: " + e);
+	            _log.finer(getPlayer().getName()+", "+getQuestName()+" cond ["+val+"] is not an integer.  Value stored, but no packet was sent: " + e);
 	        }
 		}
 
@@ -501,7 +506,7 @@ public final class QuestState
 		L2DropData d = new L2DropData();
 		d.setItemId(itemId);
 		d.setChance(chance);
-		d.setQuestID(getQuest().getName());
+		d.setQuestID(getQuestName());
 		d.addStates(new String[]{getState().getName()});
 		List<L2DropData> lst = getDrops().get(npcId);
 
@@ -593,11 +598,10 @@ public final class QuestState
 		if (count <= 0)
             return;
 
+		
+		int questId = getQuest().getQuestIntId();
 		// If item for reward is gold (ID=57), modify count with rate for quest reward
-		if (itemId == 57
-		    && !(getQuest().getQuestIntId()>=217 && getQuest().getQuestIntId()<=233)
-		    && !(getQuest().getQuestIntId()>=401 && getQuest().getQuestIntId()<=418)
-		    )
+		if (itemId == 57 && !(questId>=217 && questId<=233) && !(questId>=401 && questId<=418) )
 			count=(int)(count*Config.RATE_QUESTS_REWARD);
 		// Set quantity of item
 
@@ -952,7 +956,7 @@ public final class QuestState
 		// If quest is repeatable, delete quest from list of quest of the player and from database (quest CAN be created again => repeatable)
 		if (repeatable)
         {
-            getPlayer().delQuestState(getQuest().getName());
+            getPlayer().delQuestState(getQuestName());
 			Quest.deleteQuestInDb(this);
 
 			_vars = null;

+ 16 - 6
L2_GameServer_It/java/net/sf/l2j/gameserver/templates/L2NpcTemplate.java

@@ -310,11 +310,25 @@ public final class L2NpcTemplate extends L2CharTemplate
 			// if only one registration per npc is allowed for this event type
 			// then only register this NPC if not already registered for the specified event.
 			// if a quest allows multiple registrations, then register regardless of count
-			if (EventType.isMultipleRegistrationAllowed() || (len < 1))
+			// In all cases, check if this new registration is replacing an older copy of the SAME quest
+			if (!EventType.isMultipleRegistrationAllowed())
 			{
+				if (_quests[0].getName().equals(q.getName()))
+					_quests[0] = q;
+				else 
+					_log.warning("Quest event not allowed in multiple quests.  Skipped addition of Event Type \""+EventType+"\" for NPC \""+name +"\" and quest \""+q.getName()+"\".");
+			}
+			else
+			{
+				// be ready to add a new quest to a new copy of the list, with larger size than previously.
 				Quest[] tmp = new Quest[len+1];
+				// loop through the existing quests and copy them to the new list.  While doing so, also 
+				// check if this new quest happens to be just a replacement for a previously loaded quest.  
+				// If so, just save the updated reference and do NOT use the new list. Else, add the new
+				// quest to the end of the new list
 				for (int i=0; i < len; i++) {
-					if (_quests[i].getName().equals(q.getName())) {
+					if (_quests[i].getName().equals(q.getName())) 
+					{
 						_quests[i] = q;
 						return;
 		            }
@@ -323,10 +337,6 @@ public final class L2NpcTemplate extends L2CharTemplate
 				tmp[len] = q;
 				_questEvents.put(EventType, tmp);
 			}
-			else
-			{
-				_log.warning("Quest event not allowed in multiple quests.  Skipped addition of Event Type \""+EventType+"\" for NPC \""+name +"\" and quest \""+q.getName()+"\".");
-			}
 		}
     }