Przeglądaj źródła

refactor(quest): Small quest items handling improvements

Quest#registerQuestItems() nows adds to item list instead of overwriting it.
Added method to QuestDroplist to get all item ids.
Optimised QuestDroplist#get(npcId, itemId) for speed.
Noe Caratini 3 lat temu
rodzic
commit
95e753f964

+ 1 - 1
src/main/java/com/l2jserver/gameserver/model/events/AbstractScript.java

@@ -1813,7 +1813,7 @@ public abstract class AbstractScript implements INamable {
 	 * @param count the amount of Adena to give
 	 * @param applyRates if {@code true} quest rates will be applied to the amount
 	 */
-	public void giveAdena(L2PcInstance player, long count, boolean applyRates) {
+	public static void giveAdena(L2PcInstance player, long count, boolean applyRates) {
 		if (applyRates) {
 			rewardItems(player, Inventory.ADENA_ID, count);
 		} else {

+ 13 - 3
src/main/java/com/l2jserver/gameserver/model/quest/Quest.java

@@ -21,17 +21,20 @@ package com.l2jserver.gameserver.model.quest;
 import static com.l2jserver.gameserver.config.Configuration.general;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
 import java.util.function.Predicate;
 import java.util.logging.Level;
+import java.util.stream.IntStream;
 
 import com.l2jserver.commons.database.ConnectionFactory;
 import com.l2jserver.commons.util.Rnd;
@@ -94,7 +97,7 @@ public class Quest extends AbstractScript implements IIdentifiable {
 	protected boolean _onEnterWorld = false;
 	private boolean _isCustom = false;
 	
-	public int[] _questItemIds = null;
+	private int[] _questItemIds = null;
 	
 	private static final String DEFAULT_NO_QUEST_MSG = "<html><body>You are either not on a quest that involves this NPC, or you don't meet this NPC's minimum quest requirements.</body></html>";
 	private static final String DEFAULT_ALREADY_COMPLETED_MSG = "<html><body>This quest has already been completed.</body></html>";
@@ -2272,10 +2275,17 @@ public class Quest extends AbstractScript implements IIdentifiable {
 	
 	/**
 	 * Registers all items that have to be destroyed in case player abort the quest or finish it.
-	 * @param items
 	 */
 	public void registerQuestItems(int... items) {
-		_questItemIds = items;
+		if (_questItemIds != null) {
+			_questItemIds = IntStream.concat(Arrays.stream(_questItemIds), IntStream.of(items)).toArray();
+		} else {
+			_questItemIds = items;
+		}
+	}
+
+	public void registerQuestItems(Set<Integer> itemIds) {
+		registerQuestItems(itemIds.stream().mapToInt(i -> i).toArray());
 	}
 	
 	/**

+ 23 - 5
src/main/java/com/l2jserver/gameserver/model/quest/QuestDroplist.java

@@ -66,10 +66,13 @@ public class QuestDroplist {
             return null;
         }
 
-        return dropsByNpcId.get(npcId).stream()
-                .filter(dropInfo -> dropInfo.item().getId() == itemId)
-                .findFirst()
-                .orElse(null);
+        for (QuestDropInfo dropInfo : dropsByNpcId.get(npcId)) {
+            if (dropInfo.item().getId() == itemId) {
+                return dropInfo;
+            }
+        }
+
+        return null;
     }
 
     public QuestDropInfo get(int npcId, ItemHolder item) {
@@ -84,6 +87,21 @@ public class QuestDroplist {
         return dropsByNpcId.keySet();
     }
 
+    public Set<Integer> getItemIds() {
+        return dropsByNpcId.values().stream().flatMap(List::stream)
+                .map(QuestDropInfo::drop)
+                .flatMap(dropItem -> {
+                    if (dropItem instanceof GeneralDropItem gen) {
+                        return Stream.of(gen.getItemId());
+                    } else if (dropItem instanceof  GroupedGeneralDropItem grp) {
+                        return grp.getItems().stream().map(GeneralDropItem::getItemId);
+                    } else {
+                        return Stream.empty();
+                    }
+                })
+                .collect(Collectors.toSet());
+    }
+
     public static IDropItem singleDropItem(ItemChanceHolder itemHolder) {
         return singleDropItem(itemHolder.getId(), itemHolder.getCount(), itemHolder.getCount(), itemHolder.getChance());
     }
@@ -112,7 +130,7 @@ public class QuestDroplist {
         return groupedDropItem(chance, List.of(itemHolders));
     }
 
-    public static IDropItem groupedDropItem(double chance, List<? extends ItemChanceHolder> itemHolders) {
+    private static IDropItem groupedDropItem(double chance, List<? extends ItemChanceHolder> itemHolders) {
         GroupedGeneralDropItem group = DropListScope.QUEST.newGroupedDropItem(chance);
         List<GeneralDropItem> dropItems = itemHolders.stream()
                 .map(QuestDroplist::singleDropItem)

+ 16 - 0
src/test/java/com/l2jserver/gameserver/model/quest/QuestDroplistTest.java

@@ -712,4 +712,20 @@ public class QuestDroplistTest {
         QuestDropInfo dropInfo3 = dropList.get(1, QUEST_ITEM_3.getId());
         assertThat(dropInfo3).isNull();
     }
+
+    @Test
+    public void shouldGetAllItemIds() {
+        QuestDroplist dropList = QuestDroplist.builder()
+                .addSingleDrop(1, QUEST_ITEM_1)
+                .addGroupedDrop(2, 100.0)
+                .withDropItem(QUEST_ITEM_2)
+                .withDropItem(QUEST_ITEM_3)
+                .build()
+                .addSingleDrop(3, QUEST_ITEM_1)
+                .build();
+
+        Set<Integer> itemIds = dropList.getItemIds();
+
+        assertThat(itemIds).containsExactlyInAnyOrder(QUEST_ITEM_1.getId(), QUEST_ITEM_2.getId(), QUEST_ITEM_3.getId());
+    }
 }

+ 41 - 0
src/test/java/com/l2jserver/gameserver/model/quest/QuestTest.java

@@ -0,0 +1,41 @@
+package com.l2jserver.gameserver.model.quest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class QuestTest {
+
+    private Quest quest;
+
+    @BeforeEach
+    void setUp() {
+        quest = new Quest(1, "Test quest", "A test quest");
+    }
+
+    @Test
+    public void shouldRegisterQuestItems() {
+        quest.registerQuestItems(1, 2);
+
+        assertThat(quest.getRegisteredItemIds()).containsExactlyInAnyOrder(1, 2);
+    }
+
+    @Test
+    public void shouldRegisterQuestItemsWithSet() {
+        quest.registerQuestItems(Set.of(1, 2));
+
+        assertThat(quest.getRegisteredItemIds()).containsExactlyInAnyOrder(1, 2);
+    }
+
+    @Test
+    public void shouldAddToRegisteredQuestItemsIfCalledMultipleTimes() {
+        quest.registerQuestItems(1, 2);
+        quest.registerQuestItems(3, 4);
+        quest.registerQuestItems(Set.of(5, 6));
+
+        assertThat(quest.getRegisteredItemIds()).containsExactlyInAnyOrder(1, 2, 3, 4, 5, 6);
+    }
+}