126 lines
No EOL
5.5 KiB
C#
126 lines
No EOL
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using PhoenixLib.Events;
|
|
using PhoenixLib.Logging;
|
|
using PhoenixLib.Scheduler;
|
|
using WingsAPI.Game.Extensions.Quests;
|
|
using WingsEmu.DTOs.Quests;
|
|
using WingsEmu.Game._i18n;
|
|
using WingsEmu.Game.Characters.Events;
|
|
using WingsEmu.Game.Extensions;
|
|
using WingsEmu.Game.Networking;
|
|
using WingsEmu.Game.Quests;
|
|
using WingsEmu.Game.Quests.Event;
|
|
using WingsEmu.Packets.Enums;
|
|
using WingsEmu.Packets.Enums.Chat;
|
|
|
|
namespace Plugin.QuestImpl.Handlers
|
|
{
|
|
public class AddMainQuestEventHandler : IAsyncEventProcessor<AddQuestEvent>
|
|
{
|
|
private readonly IGameLanguageService _gameLanguageService;
|
|
private readonly IQuestFactory _questFactory;
|
|
private readonly IQuestManager _questManager;
|
|
private readonly IScheduler _scheduler;
|
|
|
|
public AddMainQuestEventHandler(IQuestManager questManager, IQuestFactory questFactory, IScheduler scheduler, IGameLanguageService gameLanguageService)
|
|
{
|
|
_questManager = questManager;
|
|
_questFactory = questFactory;
|
|
_scheduler = scheduler;
|
|
_gameLanguageService = gameLanguageService;
|
|
}
|
|
|
|
public async Task HandleAsync(AddQuestEvent e, CancellationToken cancellation)
|
|
{
|
|
IClientSession session = e.Sender;
|
|
int questId = e.QuestId;
|
|
|
|
if (e.QuestSlotType != QuestSlotType.MAIN)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QuestDto quest = _questManager.GetQuestById(questId);
|
|
if (quest == null)
|
|
{
|
|
Log.Debug($"[ERROR] Quest not found: {questId.ToString()}");
|
|
return;
|
|
}
|
|
|
|
if (session.PlayerEntity.HasQuestWithId(quest.Id))
|
|
{
|
|
session.SendMsg(_gameLanguageService.GetLanguage(GameDialogKey.QUEST_SHOUTMESSAGE_ALREADY_HAVE_QUEST, session.UserLanguage), MsgMessageType.Middle);
|
|
return;
|
|
}
|
|
|
|
// Check for possible script exploit
|
|
if (IsPotentialMainQuestExploit(session, quest))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (session.GetEmptyQuestSlot(e.QuestSlotType) == -1)
|
|
{
|
|
session.SendMsg(_gameLanguageService.GetLanguage(GameDialogKey.QUEST_SHOUTMESSAGE_SLOT_FULL, session.UserLanguage), MsgMessageType.Middle);
|
|
return;
|
|
}
|
|
|
|
CharacterQuest characterQuest = _questFactory.NewQuest(session.PlayerEntity.Id, questId, e.QuestSlotType);
|
|
session.PlayerEntity.AddActiveQuest(characterQuest);
|
|
session.RefreshQuestList(_questManager, characterQuest.QuestId);
|
|
|
|
await session.EmitEventAsync(new QuestAddedEvent
|
|
{
|
|
QuestId = characterQuest.QuestId,
|
|
QuestSlotType = characterQuest.SlotType
|
|
});
|
|
|
|
if (characterQuest.Quest.QuestType != QuestType.COMPLETE_TIMESPACE && characterQuest.Quest.QuestType != QuestType.DROP_IN_TIMESPACE && quest.TargetMapId != 0)
|
|
{
|
|
session.SendTargetQuest(quest.TargetMapX, quest.TargetMapY, quest.TargetMapId, quest.Id);
|
|
}
|
|
|
|
// Still gotta be present for NOTHING type quests
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(1), s => session.EmitEvent(new QuestCompletedEvent(characterQuest)));
|
|
}
|
|
|
|
private bool IsPotentialMainQuestExploit(IClientSession session, QuestDto quest)
|
|
{
|
|
CompletedScriptsDto lastCompletedScript = session.PlayerEntity.GetLastCompletedScript();
|
|
TutorialDto lastCompletedTutorial = _questManager.GetScriptTutorialByIndex(lastCompletedScript.ScriptId, lastCompletedScript.ScriptIndex);
|
|
|
|
IReadOnlyCollection<TutorialDto> questScripts = _questManager.GetScriptsTutorialByType(TutorialActionType.START_QUEST);
|
|
TutorialDto questScript = _questManager.GetScriptsTutorialByType(TutorialActionType.START_QUEST).FirstOrDefault(s => s.Data == quest.Id && s.Id > lastCompletedTutorial.Id);
|
|
if (questScript == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (lastCompletedTutorial != null && lastCompletedTutorial.Id > questScript.Id)
|
|
{
|
|
session.NotifyStrangeBehavior(StrangeBehaviorSeverity.SEVERE_ABUSE,
|
|
$"Tried to send an already completed quest script! | ScriptId: {questScript.ScriptId}, ScriptIndex: {questScript.ScriptIndex}");
|
|
return true;
|
|
}
|
|
|
|
IEnumerable<TutorialDto> mustBeCompletedScripts =
|
|
questScripts.Where(s => s.ScriptId < questScript.ScriptId || s.ScriptId == questScript.ScriptId && s.ScriptIndex < questScript.ScriptIndex);
|
|
foreach (TutorialDto tutorialDto in mustBeCompletedScripts)
|
|
{
|
|
if (!session.PlayerEntity.HasCompletedScriptByIndex(tutorialDto.ScriptId, tutorialDto.ScriptIndex))
|
|
{
|
|
session.NotifyStrangeBehavior(StrangeBehaviorSeverity.SEVERE_ABUSE,
|
|
$"Tried to send a quest script without having completed previous ones! | ScriptId: {questScript.ScriptId}, ScriptIndex: {questScript.ScriptIndex} | "
|
|
+ $"The script that was incompleted and triggered this message was: ScriptId: {tutorialDto.ScriptId} ; ScriptIndex: {tutorialDto.ScriptIndex}");
|
|
return true; // Let's hope doesn't explode
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
} |