QuestManager.java 5.88 KB
Newer Older
Melledy's avatar
Melledy committed
1
2
package emu.grasscutter.game.quest;

Akka's avatar
Akka committed
3
import java.util.*;
Melledy's avatar
Melledy committed
4
import java.util.function.Consumer;
Akka's avatar
Akka committed
5
import java.util.stream.Collectors;
Melledy's avatar
Melledy committed
6

Akka's avatar
Akka committed
7
import emu.grasscutter.Grasscutter;
Melledy's avatar
Melledy committed
8
import emu.grasscutter.data.GameData;
Akka's avatar
Akka committed
9
import emu.grasscutter.data.binout.MainQuestData;
Melledy's avatar
Melledy committed
10
11
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
Melledy's avatar
Melledy committed
12
13
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.Player;
Akka's avatar
Akka committed
14
import emu.grasscutter.game.quest.enums.ParentQuestState;
Melledy's avatar
Melledy committed
15
import emu.grasscutter.game.quest.enums.QuestTrigger;
16
import emu.grasscutter.game.quest.enums.LogicType;
Melledy's avatar
Melledy committed
17
import emu.grasscutter.game.quest.enums.QuestState;
Akka's avatar
Akka committed
18
import emu.grasscutter.server.packet.send.*;
Melledy's avatar
Melledy committed
19
20
21
22
23
24
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;

public class QuestManager {
	private final Player player;
	private final Int2ObjectMap<GameMainQuest> quests;
Akka's avatar
Akka committed
25

Melledy's avatar
Melledy committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	public QuestManager(Player player) {
		this.player = player;
		this.quests = new Int2ObjectOpenHashMap<>();
	}

	public Player getPlayer() {
		return player;
	}

	public Int2ObjectMap<GameMainQuest> getQuests() {
		return quests;
	}
	
	public GameMainQuest getMainQuestById(int mainQuestId) {
		return getQuests().get(mainQuestId);
	}
	
	public GameQuest getQuestById(int questId) {
Melledy's avatar
Melledy committed
44
		QuestData questConfig = GameData.getQuestDataMap().get(questId);
Melledy's avatar
Melledy committed
45
46
47
48
		if (questConfig == null) {
			return null;
		}
		
Melledy's avatar
Melledy committed
49
		GameMainQuest mainQuest = getQuests().get(questConfig.getMainId());
Melledy's avatar
Melledy committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
		
		if (mainQuest == null) {
			return null;
		}
		
		return mainQuest.getChildQuests().get(questId);
	}
	
	public void forEachQuest(Consumer<GameQuest> callback) {
		for (GameMainQuest mainQuest : getQuests().values()) {
			for (GameQuest quest : mainQuest.getChildQuests().values()) {
				callback.accept(quest);
			}
		}
	}
65
66
67
68
69
70

	public void forEachMainQuest(Consumer<GameMainQuest> callback) {
		for (GameMainQuest mainQuest : getQuests().values()) {
			callback.accept(mainQuest);
		}
	}
Melledy's avatar
Melledy committed
71
	
72
73
74
75
76
77
78
79
80
81
82
	// TODO
	public void forEachActiveQuest(Consumer<GameQuest> callback) {
		for (GameMainQuest mainQuest : getQuests().values()) {
			for (GameQuest quest : mainQuest.getChildQuests().values()) {
				if (quest.getState() != QuestState.QUEST_STATE_FINISHED) {
					callback.accept(quest);
				}
			}
		}
	}
	
Melledy's avatar
Melledy committed
83
84
	public GameMainQuest addMainQuest(QuestData questConfig) {
		GameMainQuest mainQuest = new GameMainQuest(getPlayer(), questConfig.getMainId());
Melledy's avatar
Melledy committed
85
86
87
88
89
90
91
92
		getQuests().put(mainQuest.getParentQuestId(), mainQuest);

		getPlayer().sendPacket(new PacketFinishedParentQuestUpdateNotify(mainQuest));
		
		return mainQuest;
	}
	
	public GameQuest addQuest(int questId) {
Melledy's avatar
Melledy committed
93
		QuestData questConfig = GameData.getQuestDataMap().get(questId);
Melledy's avatar
Melledy committed
94
95
96
97
98
		if (questConfig == null) {
			return null;
		}
		
		// Main quest
Melledy's avatar
Melledy committed
99
		GameMainQuest mainQuest = this.getMainQuestById(questConfig.getMainId());
Melledy's avatar
Melledy committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
		
		// Create main quest if it doesnt exist
		if (mainQuest == null) {
			mainQuest = addMainQuest(questConfig);
		}
		
		// Sub quest
		GameQuest quest = mainQuest.getChildQuestById(questId);
		
		if (quest != null) {
			return null;
		}

		// Create
		quest = new GameQuest(mainQuest, questConfig);

		// Save main quest
		mainQuest.save();

		// Send packet
		getPlayer().sendPacket(new PacketQuestListUpdateNotify(quest));

		return quest;
	}
Akka's avatar
Akka committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    public void startMainQuest(int mainQuestId){
        var mainQuestData = GameData.getMainQuestDataMap().get(mainQuestId);

        if (mainQuestData == null){
            return;
        }

        Arrays.stream(mainQuestData.getSubQuests())
            .min(Comparator.comparingInt(MainQuestData.SubQuestData::getOrder))
            .map(MainQuestData.SubQuestData::getSubId)
            .ifPresent(this::addQuest);
    }
    public void triggerEvent(QuestTrigger condType, int... params) {
        triggerEvent(condType, "", params);
    }

	public void triggerEvent(QuestTrigger condType, String paramStr, int... params) {
        Grasscutter.getLogger().debug("Trigger Event {}, {}, {}", condType, paramStr, params);
142
		Set<GameQuest> changedQuests = new HashSet<>();
Akka's avatar
Akka committed
143

144
		this.forEachActiveQuest(quest -> {
Melledy's avatar
Melledy committed
145
			QuestData data = quest.getData();
Akka's avatar
Akka committed
146
147
148

			for (int i = 0; i < data.getFinishCond().size(); i++) {
				if (quest.getFinishProgressList() == null
149
150
					|| quest.getFinishProgressList().length == 0
					|| quest.getFinishProgressList()[i] == 1) {
151
152
					continue;
				}
Akka's avatar
Akka committed
153
154
155

				QuestCondition condition = data.getFinishCond().get(i);

156
157
158
				if (condition.getType() != condType) {
					continue;
				}
Akka's avatar
Akka committed
159
160
161

				boolean result = getPlayer().getServer().getQuestHandler().triggerContent(quest, condition, paramStr, params);

162
163
				if (result) {
					quest.getFinishProgressList()[i] = 1;
Akka's avatar
Akka committed
164

165
166
167
168
					changedQuests.add(quest);
				}
			}
		});
Akka's avatar
Akka committed
169

170
		for (GameQuest quest : changedQuests) {
Melledy's avatar
Melledy committed
171
			LogicType logicType = quest.getData().getFailCondComb();
172
			int[] progress = quest.getFinishProgressList();
Akka's avatar
Akka committed
173

174
175
176
177
178
179
180
181
182
183
184
185
			// Handle logical comb
			boolean finish = LogicType.calculate(logicType, progress);

			// Finish
			if (finish) {
				quest.finish();
			} else {
				getPlayer().sendPacket(new PacketQuestProgressUpdateNotify(quest));
				quest.save();
			}
		}
	}
Melledy's avatar
Melledy committed
186

Akka's avatar
Akka committed
187
188
189
190
191
192
193
194
195
    public List<QuestGroupSuite> getSceneGroupSuite(int sceneId) {
        return getQuests().values().stream()
            .filter(i -> i.getState() != ParentQuestState.PARENT_QUEST_STATE_FINISHED)
            .map(GameMainQuest::getQuestGroupSuites)
            .filter(Objects::nonNull)
            .flatMap(Collection::stream)
            .filter(i -> i.getScene() == sceneId)
            .toList();
    }
Melledy's avatar
Melledy committed
196
197
198
199
200
201
202
203
	public void loadFromDatabase() {
		List<GameMainQuest> quests = DatabaseHelper.getAllQuests(getPlayer());
		
		for (GameMainQuest mainQuest : quests) {
			mainQuest.setOwner(this.getPlayer());
			
			for (GameQuest quest : mainQuest.getChildQuests().values()) {
				quest.setMainQuest(mainQuest);
Melledy's avatar
Melledy committed
204
				quest.setConfig(GameData.getQuestDataMap().get(quest.getQuestId()));
Melledy's avatar
Melledy committed
205
206
207
208
209
210
			}
			
			this.getQuests().put(mainQuest.getParentQuestId(), mainQuest);
		}
	}
}