Implement group-based item giving & Add content handler for item giving

This commit is contained in:
KingRainbow44
2023-08-13 00:32:02 -04:00
Unverified
parent afc5841596
commit 40bbfd90e1
12 changed files with 371 additions and 138 deletions
@@ -2,33 +2,26 @@ package emu.grasscutter.game.quest;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.binout.ScenePointEntry;
import emu.grasscutter.data.binout.*;
import emu.grasscutter.data.excels.quest.QuestData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.BasePlayerManager;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.*;
import emu.grasscutter.game.quest.enums.*;
import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify;
import emu.grasscutter.server.packet.send.PacketQuestGlobalVarNotify;
import emu.grasscutter.game.world.Position;
import emu.grasscutter.net.proto.GivingRecordOuterClass.GivingRecord;
import emu.grasscutter.server.packet.send.*;
import io.netty.util.concurrent.FastThreadLocalThread;
import it.unimi.dsi.fastutil.ints.*;
import lombok.Getter;
import lombok.val;
import lombok.*;
import javax.annotation.Nonnull;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static emu.grasscutter.GameConstants.DEBUG;
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
import static emu.grasscutter.config.Configuration.SERVER;
import static emu.grasscutter.config.Configuration.*;
public final class QuestManager extends BasePlayerManager {
@Getter private final Player player;
@@ -36,52 +29,13 @@ public final class QuestManager extends BasePlayerManager {
@Getter private final Int2ObjectMap<GameMainQuest> mainQuests;
@Getter private final List<Integer> loggedQuests;
@Getter private final List<Integer> activeGivings = new ArrayList<>();
private long lastHourCheck = 0;
private long lastDayCheck = 0;
public static final ExecutorService eventExecutor;
static {
eventExecutor = new ThreadPoolExecutor(4, 4,
60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000),
FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy());
}
/*
On SetPlayerBornDataReq, the server sends FinishedParentQuestNotify, with this exact
parentQuestList. Captured on Game version 2.7
Note: quest 40063 is already set to finished, with childQuest 4006406's state set to 3
*/
private static Set<Integer> newPlayerMainQuests = Set.of(303,318,348,349,350,351,416,500,
501,502,503,504,505,506,507,508,509,20000,20507,20509,21004,21005,21010,21011,21016,21017,
21020,21021,21025,40063,70121,70124,70511,71010,71012,71013,71015,71016,71017,71555);
/*
On SetPlayerBornDataReq, the server sends ServerCondMeetQuestListUpdateNotify, with this exact
addQuestIdList. Captured on Game version 2.7
Total of 161...
*/
/*
private static Set<Integer> newPlayerServerCondMeetQuestListUpdateNotify = Set.of(3100101, 7104405, 2201601,
7100801, 1907002, 7293301, 7193801, 7293401, 7193901, 7091001, 7190501, 7090901, 7190401, 7090801, 7190301,
7195301, 7294801, 7195201, 7293001, 7094001, 7193501, 7293501, 7194001, 7293701, 7194201, 7194301, 7293801,
7194901, 7194101, 7195001, 7294501, 7294101, 7194601, 7294301, 7194801, 7091301, 7290301, 2102401, 7216801,
7190201, 7090701, 7093801, 7193301, 7292801, 7227828, 7093901, 7193401, 7292901, 7093701, 7193201, 7292701,
7082402, 7093601, 7292601, 7193101, 2102301, 7093501, 7292501, 7193001, 7093401, 7292401, 7192901, 7093301,
7292301, 7192801, 7294201, 7194701, 2100301, 7093201, 7212402, 7292201, 7192701, 7280001, 7293901, 7194401,
7093101, 7212302, 7292101, 7192601, 7093001, 7292001, 7192501, 7216001, 7195101, 7294601, 2100900, 7092901,
7291901, 7192401, 7092801, 7291801, 7192301, 2101501, 7092701, 7291701, 7192201, 7106401, 2100716, 7091801,
7290801, 7191301, 7293201, 7193701, 7094201, 7294001, 7194501, 2102290, 7227829, 7193601, 7094101, 7091401,
7290401, 7190901, 7106605, 7291601, 7192101, 7092601, 7291501, 7192001, 7092501, 7291401, 7191901, 7092401,
7291301, 7191801, 7092301, 7211402, 7291201, 7191701, 7092201, 7291101, 7191601, 7092101, 7291001, 7191501,
7092001, 7290901, 7191401, 7091901, 7290701, 7191201, 7091701, 7290601, 7191101, 7091601, 7290501, 7191001,
7091501, 7290201, 7190701, 7091201, 7190601, 7091101, 7190101, 7090601, 7090501, 7090401, 7010701, 7090301,
7090201, 7010103, 7090101
);
*/
public static final ExecutorService eventExecutor
= new ThreadPoolExecutor(4, 4,
60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000),
FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy());
public static long getQuestKey(int mainQuestId) {
QuestEncryptionKey questEncryptionKey = GameData.getMainQuestEncryptionMap().get(mainQuestId);
@@ -137,20 +91,99 @@ public final class QuestManager extends BasePlayerManager {
return GAME_OPTIONS.questing.enabled;
}
public void onPlayerBorn() {
// TODO scan the quest and start the quest with acceptCond fulfilled
// The off send 3 request in that order:
// 1. FinishedParentQuestNotify
// 2. QuestListNotify
// 3. ServerCondMeetQuestListUpdateNotify
/**
* Attempts to add the giving action.
*
* @param givingId The giving action ID.
* @throws IllegalStateException If the giving action is already active.
*/
public void addGiveItemAction(int givingId)
throws IllegalStateException {
var progress = this.player.getPlayerProgress();
var givings = progress.getItemGivings();
if (this.isQuestingEnabled()) {
this.enableQuests();
// Check if the action is already present.
if (givings.containsKey(givingId)) {
throw new IllegalStateException("Giving action " + givingId + " is already active.");
}
// this.getPlayer().sendPacket(new PacketFinishedParentQuestUpdateNotify(newQuests));
// this.getPlayer().sendPacket(new PacketQuestListNotify(subQuests));
// this.getPlayer().sendPacket(new PacketServerCondMeetQuestListUpdateNotify(newPlayerServerCondMeetQuestListUpdateNotify));
// Add the action.
givings.put(givingId, ItemGiveRecord.resolve(givingId));
// Save the givings.
player.save();
this.sendGivingRecords();
}
/**
* Marks a giving action as completed.
*
* @param givingId The giving action ID.
*/
public void markCompleted(int givingId) {
var progress = this.player.getPlayerProgress();
var givings = progress.getItemGivings();
// Check if the action is already present.
if (!givings.containsKey(givingId)) {
throw new IllegalStateException("Giving action " + givingId + " is not active.");
}
// Mark the action as finished.
givings.get(givingId).setFinished(true);
// Save the givings.
player.save();
this.sendGivingRecords();
}
/**
* Attempts to remove the giving action.
*
* @param givingId The giving action ID.
*/
public void removeGivingItemAction(int givingId) {
var progress = this.player.getPlayerProgress();
var givings = progress.getItemGivings();
// Check if the action is already present.
if (!givings.containsKey(givingId)) {
throw new IllegalStateException("Giving action " + givingId + " is not active.");
}
// Remove the action.
givings.remove(givingId);
// Save the givings.
player.save();
this.sendGivingRecords();
}
/**
* @return Serialized giving records to be used in a packet.
*/
public Collection<GivingRecord> getGivingRecords() {
return this.getPlayer().getPlayerProgress()
.getItemGivings().values().stream()
.map(ItemGiveRecord::toProto)
.toList();
}
/**
* Attempts to remove the giving action.
*/
public void sendGivingRecords() {
// Send the record to the player.
this.player.sendPacket(
new PacketGivingRecordNotify(
this.getGivingRecords()));
}
public void onPlayerBorn() {
if (this.isQuestingEnabled()) {
this.enableQuests();
this.sendGivingRecords();
}
}
public void onLogin() {