using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using ServerCore; using ServerBase; using ServerCommon; using ServerCommon.BusinessLogDomain; using MetaAssets; namespace GameServer; public class AcceptQuestVariable { public QuestBaseInfo? m_quest_base_info_nullable { get; set; } = null; public bool m_is_mail_quest { get; set; } = false; public ServerCommon.Quest? m_new_quest_nullable { get; set; } = null; public MetaAssets.EQuestType m_quest_type { get; set; } = MetaAssets.EQuestType.NONE; public Int32 m_quest_cost { get; set; } = 0; //public CommonResult m_common_result { get; set; } = new(); public List assignable_quests { get; set; } = new(); public AcceptQuestVariable() { m_quest_base_info_nullable = null; m_is_mail_quest = false; m_quest_type = MetaAssets.EQuestType.NONE; m_new_quest_nullable = null; } public AcceptQuestVariable(QuestBaseInfo metaInfo, bool isMailQuest, ServerCommon.Quest quest, Int32 questCost = 0) { m_quest_base_info_nullable = metaInfo; m_is_mail_quest = isMailQuest; m_new_quest_nullable = quest; if (false == EnumHelper.tryParse(metaInfo.QuestType, out MetaAssets.EQuestType quest_type)) { m_quest_type = MetaAssets.EQuestType.NONE; } else m_quest_type = quest_type; m_quest_cost = questCost; } } public class QuestAcceptAction : EntityActionBase { public QuestAcceptAction(EntityBase owner) : base(owner) {} public override async Task onInit() { await Task.CompletedTask; var result = new Result(); return result; } public override void onClear() { return; } public async Task acceptQuestConditionCheck(UInt32 questId, AcceptQuestVariable acceptQuestVar) { var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var quest_action = owner.getEntityAction(); var quest_mail_action = owner.getEntityAction(); var end_quest_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(quest_action); NullReferenceCheckHelper.throwIfNull(quest_mail_action); NullReferenceCheckHelper.throwIfNull(end_quest_action); //해당 퀘스트 정보 불러오기 (var result, var quest_meta_all_base_info) = await QuestMetaManager.It.getQuestMeta(questId); if (result.isFail()) return result; var quest_base_info = quest_meta_all_base_info.m_quest_base_info; acceptQuestVar.m_quest_base_info_nullable = quest_base_info; NullReferenceCheckHelper.throwIfNull(acceptQuestVar.m_quest_base_info_nullable, () => $"acceptQuestVar.m_quest_base_info_nullable is null !!!"); if (false == EnumHelper.tryParse(acceptQuestVar.m_quest_base_info_nullable.QuestType, out MetaAssets.EQuestType quest_type)) { result.setFail(ServerErrorCode.ServerLogicError, $"QuestType Parse Failed : {acceptQuestVar.m_quest_base_info_nullable.QuestType}"); return result; } acceptQuestVar.m_quest_type = quest_type; //현재 보유중인 퀘스트인지 체크 quest_action.getQuest(quest_type, questId, out var existedQuest); if (existedQuest is not null) { result.setFail(ServerErrorCode.QuestAlreadyExist, $"Quest Already Exist quest Type : {acceptQuestVar.m_quest_base_info_nullable.QuestType}, questId : {questId}"); return result; } //메일로 받는 경우 메일 가지고 있는지 체크 acceptQuestVar.m_is_mail_quest = acceptQuestVar.m_quest_base_info_nullable.AssignType.Equals(MetaAssets.EAssignType.MAIL.ToString()); if (acceptQuestVar.m_is_mail_quest) { result = quest_mail_action.hasQuestMail(quest_type, questId, true); if (result.isFail()) return result; } //이미 완료한 퀘스트 인지 체크 result = end_quest_action.endQuestCheck(quest_type, questId, 0); if (result.isFail()) return result; //내가 들고 있는 퀘스트의 전체 타입 수를 정리 하고 이미 퀘스트가 꽉차서 받을 수 없으면 에러 처리 result = quest_action.assignableQuestCheckByQuestType(acceptQuestVar.m_quest_type); if (result.isFail()) return result; return result; } public (Result, AcceptQuestVariable) acceptQuestByNpcDialogue(QuestBaseInfo questMetaInfo) { var owner = getOwner() as Player; ArgumentNullException.ThrowIfNull(owner); var new_quest = new ServerCommon.Quest(owner, owner.getUserGuid()); ArgumentNullException.ThrowIfNull(new_quest); var quest_attribute = new_quest.getEntityAttribute(); ArgumentNullException.ThrowIfNull(quest_attribute); AcceptQuestVariable acceptQuestVar = new(questMetaInfo, false, new_quest); var result = newQuestAssign(ref acceptQuestVar); if (result.isFail()) { return (result, acceptQuestVar); } return (result, acceptQuestVar); } public async Task<(Result, AcceptQuestVariable?)> questAccept(UInt32 questId) { var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner); var quest_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(quest_action); (var result, var quest_meta_all_base_info) = await QuestMetaManager.It.getQuestMeta(questId); if (result.isFail()) return (result, null); var quest_base_info = quest_meta_all_base_info.m_quest_base_info; NullReferenceCheckHelper.throwIfNull(quest_base_info, () => $"quest_base_info is null !!!"); var new_quest = new ServerCommon.Quest(owner, owner.getUserGuid()); AcceptQuestVariable acceptQuestVar = new(quest_base_info, false, new_quest); result = newQuestAssign(ref acceptQuestVar); if (result.isFail()) return (result, null); return (result, acceptQuestVar); } public Result makeNewQuestAssignInfo(ref AcceptQuestVariable acceptQuestVar, Int32 cost = 0) { var result = new Result(); var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner); var quest_meta = acceptQuestVar.m_quest_base_info_nullable; NullReferenceCheckHelper.throwIfNull(quest_meta, () => $"quest_meta is null !!!"); acceptQuestVar.m_new_quest_nullable = new ServerCommon.Quest(owner, owner.getUserGuid()); var quest_attribute = acceptQuestVar.m_new_quest_nullable.getEntityAttribute(); ArgumentNullException.ThrowIfNull(quest_attribute); DateTime nowDt = DateTimeHelper.Current; quest_attribute.QuestId = quest_meta.QuestId; quest_attribute.QuestType = acceptQuestVar.m_quest_type; quest_attribute.UgqInfo.QuestRevision = quest_meta.QuestRevision; quest_attribute.UgqInfo.QuestCost = cost; quest_attribute.UgqInfo.UqgState = quest_meta.UgqState; quest_attribute.QuestAssignTime = nowDt; quest_attribute.CurrentTaskNum = 1; quest_attribute.CurrentTaskComplete = 0; quest_attribute.TaskStartTime = nowDt; quest_attribute.QuestCompleteTime = nowDt; quest_attribute.IsComplete = 0; quest_attribute.HasTimer = 0; quest_attribute.TimerCompleteTime = nowDt; quest_attribute.CompletedIdxStrings = new(); if (false == quest_meta.QuestTaskGroupList.TryGetValue(quest_attribute.CurrentTaskNum, out var quest_task_info)) { result.setFail(ServerErrorCode.QuestInvalidValue, $"questEventInfo InvalidData questId = {quest_attribute.QuestId}, info.CurrentTaskNum : {quest_attribute.CurrentTaskNum}"); return result; } quest_attribute.ActiveEvents.AddRange(QuestManager.It.getActiveEventStrings(quest_attribute, quest_task_info)); if (quest_task_info.HasCounter) { quest_attribute.HasCounter = (quest_task_info.HasCounter ? 1 : 0); quest_attribute.MinCounter = quest_task_info.MinCounter; quest_attribute.MaxCounter = quest_task_info.MaxCounter; quest_attribute.CurrentCounter = quest_task_info.MinCounter; } if (quest_task_info.HasTimer) { quest_attribute.HasCounter = (quest_task_info.HasCounter ? 1 : 0); quest_attribute.TimerCompleteTime = nowDt.AddSeconds(quest_task_info.RemainTime); } if (quest_task_info.HasAssignableQuest) { acceptQuestVar.assignable_quests.AddRange(quest_task_info.AssignableQuestIds); } quest_attribute.newEntityAttribute(); return result; } public async Task reAssignQuest(UInt32 questId, UInt32 questRevision) { (var result, var quest) = await questAcceptWithTransaction(questId, questRevision, 0); return result; } public async Task<(Result, ServerCommon.Quest?)> questAcceptWithTransaction(UInt32 questId, UInt32 questRevision, int recursiveCount) { var result = new Result(); if (recursiveCount > 10) { var err_msg = $"recursiveCount > 10 !!! : {recursiveCount}"; Log.getLogger().error(err_msg); result.setFail(ServerErrorCode.ServerLogicError, err_msg); return (result, null); } recursiveCount += 1; var player = getOwner() as Player; ArgumentNullException.ThrowIfNull(player); var quest_action = player.getEntityAction(); ArgumentNullException.ThrowIfNull(quest_action); (result, var quest_meta_all_base_info) = await QuestMetaManager.It.getQuestMeta(player, questId, questRevision); if (result.isFail()) return (result, null); var quest_base_info = quest_meta_all_base_info.m_quest_base_info; NullReferenceCheckHelper.throwIfNull(quest_base_info, () => $"quest_base_info is null !!!"); var server_logic = GameServerApp.getServerLogic(); NullReferenceCheckHelper.throwIfNull(server_logic); var new_quest = new ServerCommon.Quest(player, player.getUserGuid()); NullReferenceCheckHelper.throwIfNull(new_quest); AcceptQuestVariable acceptQuestVar = new(quest_base_info, false, new_quest); var fn_quest_accept = async delegate () { var result = new Result(); result = newQuestAssign(ref acceptQuestVar); if (result.isFail()) return result; var batch = new QueryBatchEx(player, LogActionType.None, server_logic.getDynamoDbClient()); { batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner()); } batch.appendBusinessLog(new QuestAcceptBusinessLog(questId, questRevision, acceptQuestVar.m_quest_type)); result = await QueryHelper.sendQueryAndBusinessLog(batch); if (result.isFail()) return result; return result; }; result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "QuestAcceptWithTran", fn_quest_accept); if (result.isFail()) { var err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}"; Log.getLogger().error(err_msg); return (result, null); } NullReferenceCheckHelper.throwIfNull(acceptQuestVar.m_new_quest_nullable, () => $"acceptQuestVar.m_new_quest_nullable is null !!!"); quest_action.addNewQuest(questId, acceptQuestVar.m_new_quest_nullable); await player.send_GS2C_NTF_QUEST_UPDATE(questId, questRevision, new(), true); await QuestManager.It.QuestCheck(player, new QuestMail(EQuestEventTargetType.QUEST, EQuestEventNameType.ACTIVED, "")); var quest_mail_action = player.getEntityAction(); ArgumentNullException.ThrowIfNull(quest_mail_action); quest_mail_action.GS2C_NTF_DELETE_QUEST_MAIL_NOTI(questId); foreach(var additional_quest_id in acceptQuestVar.assignable_quests) { await questAcceptWithTransaction(additional_quest_id, 0, recursiveCount); } return (result, new_quest); } public Result newQuestAssign(ref AcceptQuestVariable acceptQuestVar) { var owner = getOwner() as Player; ArgumentNullException.ThrowIfNull(owner); //퀘스트 객체 데이터 채우기 var result = makeNewQuestAssignInfo(ref acceptQuestVar); if (result.isFail()) return result; return result; } }