초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,478 @@
using System;
using System.Globalization;
using Microsoft.IdentityModel.Tokens;
using Pipelines.Sockets.Unofficial.Arenas;
using ServerCommon;
using UGQDataAccess;
using UGQDatabase.Models;
using UGQApiServer.Converter;
using UGQApiServer.Models;
using UGQApiServer.UGQData;
namespace UGQApiServer.Validation;
public enum ValidationErrorKind
{
Success,
RequireBeaconId, // <20><><EFBFBD><EFBFBD> <20>Է<EFBFBD> <20>ʿ<EFBFBD>
NotFoundBeaconId, // <20>Էµ<D4B7> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߸<EFBFBD><DFB8><EFBFBD> <20><><EFBFBD>̵<EFBFBD>
FirstTaskIsNotTalkAction, // ù<><C3B9><EFBFBD><EFBFBD> <20>½<EFBFBD>ũ <20><>ȭ <20>׼<EFBFBD><D7BC><EFBFBD> <20>ƴ<EFBFBD>
FirstTaskIsNotSameBeacon, // ù<><C3B9><EFBFBD><EFBFBD> <20>½<EFBFBD>ũ<EFBFBD><C5A9> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٸ<EFBFBD>
InvalidCostAmount, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
InvalidDialogType, // <20>Է<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
InvalidDialogConditionId, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
InvalidDialogConditionValue, // <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
InvalidDialogNextSequence, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
InvalidSequenceCount, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3~30<33><30> <20><><EFBFBD><EFBFBD>
DontHaveEndSequence, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD>
NotSetPlayerTalker, // Player Talker<65><72> <20><><EFBFBD>õǾ<C3B5> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
InvalidTalkerOrder, // Npc <20>ڿ<EFBFBD> Player<65><72> <20><> <20><> <20><><EFBFBD><EFBFBD>
InvalidTaskActionId, // Task <20>׼<EFBFBD> Ÿ<><C5B8> <20><><EFBFBD><EFBFBD>
InvalidTaskActionValue, // Task <20>׼<EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
InvalidTaskCount, // Task <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3~20<32><30> <20><><EFBFBD><EFBFBD>
DontHaveTitleImage, // Ÿ<><C5B8>Ʋ <20>̹<EFBFBD><CCB9><EFBFBD> <20><><EFBFBD><EFBFBD>
DontHaveBannerImage, // <20><><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD> <20><><EFBFBD><EFBFBD>
InvalidNpcActionId, // Npc <20>׼<EFBFBD> Ÿ<><C5B8> <20><><EFBFBD><EFBFBD>
}
public class ValidationError
{
public ValidationErrorKind Kind { get; set; }
public override string ToString()
{
return "";
}
}
public class QuestDialogValidatorError : ValidationError
{
public int TaskIndex { get; set; } = -1;
public int SequenceId { get; set; } = -1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB><EFBFBD> SequenceId.
public int SequenceActionIndex { get; set; } = -1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB><EFBFBD> SequenceAction <20><>ġ. 0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. -1<><31> <20>׼<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ<EFBFBD>.
public override string ToString()
{
// Kind<6E><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>޽<EFBFBD><DEBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD>
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
string position = "";
if (SequenceActionIndex != -1)
{
position = $"[TaskIndex: {TaskIndex}, SequenceId: {SequenceId}, SequenceActionIndex: {SequenceActionIndex}] ";
}
else if (SequenceId != -1)
{
position = $"[TaskIndex: {TaskIndex}, SequenceId: {SequenceId}] ";
}
else
{
position = $"[TaskIndex: {TaskIndex}] ";
}
var textId = $"UGQ_Validator_Error_{Kind.ToString()}";
var message = UGQDataHelper.getText(langEnum, textId);
return $"{position}{message}";
}
}
public class QuestContentValidatorError : ValidationError
{
public int TaskIndex { get; set; } = -1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB><EFBFBD> Task <20><>ġ. 0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public override string ToString()
{
// Kind<6E><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>޽<EFBFBD><DEBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD>
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
string position = "";
if (TaskIndex != -1)
{
position = $"[TaskIndex: {TaskIndex}] ";
}
else
{
position = "";
}
var textId = $"UGQ_Validator_Error_{Kind.ToString()}";
var message = UGQDataHelper.getText(langEnum, textId);
return $"{position}{message ?? "Unkonwn"}";
}
}
public class UGQValidator
{
UGQMetaData _ugqMetadata;
int MIN_SEQUENCE = 3;
int MAX_SEQUENCE = 30;
int MIN_TASK = 3;
int MAX_TASK = 20;
public UGQValidator(UGQMetaData ugqMetadata)
{
_ugqMetadata = ugqMetadata;
}
public List<ValidationError> Validate(QuestContentEntity questContent, List<QuestDialogEntity> questDialogs)
{
List<ValidationError> errors = new();
ValidateQuestContent(questContent, errors);
// <20><><EFBFBD>̾<EFBFBD><CCBE>α<EFBFBD> üũ
foreach (var (index, task) in questContent.Tasks.Select((task, index) => (index, task)))
{
var dialogIndex = questDialogs.FindIndex(x => x.Id == task.DialogId);
if (task.ActionId == UGQMetaData.TALK_ACTION_ID)
{
if (dialogIndex == -1)
{
// Talk <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD> Dialog<6F><67> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.InvalidSequenceCount,
TaskIndex = index,
};
errors.Add(error);
continue;
}
var questDialog = questDialogs[dialogIndex];
// sequence <20><><EFBFBD><EFBFBD> üũ
if (questDialog.Sequences.Count < MIN_SEQUENCE || questDialog.Sequences.Count >= MAX_SEQUENCE)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.InvalidSequenceCount,
TaskIndex = index,
};
errors.Add(error);
}
ValidateQuestDialog(index, questDialog, errors);
}
}
return errors;
}
int getCost(UgqGradeType gradeType)
{
switch (gradeType)
{
case UgqGradeType.Amature:
return MetaHelper.GameConfigMeta.UgqUsageFeeAmateur;
case UgqGradeType.RisingStar:
return MetaHelper.GameConfigMeta.UgqUsageFeeRisingStar;
case UgqGradeType.Master1:
return MetaHelper.GameConfigMeta.UgqUsageFeeMaster1;
case UgqGradeType.Master2:
return MetaHelper.GameConfigMeta.UgqUsageFeeMaster2;
case UgqGradeType.Master3:
return MetaHelper.GameConfigMeta.UgqUsageFeeMaster3;
}
return 0;
}
void ValidateQuestContent(QuestContentEntity questContent, List<ValidationError> errors)
{
if(questContent.BeaconId == 0 && string.IsNullOrEmpty(questContent.UgcBeaconGuid) == true)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.RequireBeaconId,
};
errors.Add(error);
}
if(questContent.BeaconId != 0)
{
var errorKind = _ugqMetadata.isValidNpcId(questContent.BeaconId);
if (errorKind != ValidationErrorKind.Success)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = errorKind,
};
errors.Add(error);
}
}
if (questContent.Tasks.Count < MIN_TASK || questContent.Tasks.Count >= MAX_TASK)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.InvalidTaskCount,
};
errors.Add(error);
}
if (string.IsNullOrEmpty(questContent.TitleImagePath) == true)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.DontHaveTitleImage,
};
errors.Add(error);
}
if (string.IsNullOrEmpty(questContent.BannerImagePath) == true)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.DontHaveBannerImage,
};
errors.Add(error);
}
//if (questContent.Cost != getCost(questContent.GradeType))
//{
// QuestContentValidatorError error = new QuestContentValidatorError
// {
// Kind = ValidationErrorKind.InvalidCostAmount,
// };
// errors.Add(error);
//}
if (questContent.Tasks[0].ActionId != 1)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.FirstTaskIsNotTalkAction,
TaskIndex = 0,
};
errors.Add(error);
}
bool validTalkBeacon = false;
if (questContent.BeaconId != 0 && questContent.Tasks[0].ActionValue == questContent.BeaconId)
validTalkBeacon = true;
if (string.IsNullOrEmpty(questContent.UgcBeaconGuid) == false && questContent.Tasks[0].UgcActionValueGuid == questContent.UgcBeaconGuid)
validTalkBeacon = true;
if(validTalkBeacon == false)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = ValidationErrorKind.FirstTaskIsNotSameBeacon,
TaskIndex = 0,
};
errors.Add(error);
}
foreach (var (index, task) in questContent.Tasks.Select((task, index) => (index, task)))
{
if (string.IsNullOrEmpty(task.UgcActionValueGuid) == false)
{
var errorKind = _ugqMetadata.isValidTackActionId(task.ActionId);
if (errorKind != ValidationErrorKind.Success)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = errorKind,
TaskIndex = index,
};
errors.Add(error);
}
}
else
{
var errorKind = _ugqMetadata.isValidTackActionValue(task.ActionId, task.ActionValue);
if (errorKind != ValidationErrorKind.Success)
{
QuestContentValidatorError error = new QuestContentValidatorError
{
Kind = errorKind,
TaskIndex = index,
};
errors.Add(error);
}
}
}
}
void ValidateQuestDialogSequenceAction(int taskIndex, List<int> sequenceIds, int sequenceId, int actionIdex, DialogSequenceActionEntity sequenceAction, List<ValidationError> errors)
{
if (sequenceAction.Talker == DialogTalker.Player)
{
// Talker<65><72> <20>÷<EFBFBD><C3B7>̾<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> üũ
var errorKind = _ugqMetadata.isValidDialogActionValue(sequenceAction.Type, sequenceAction.Condition, sequenceAction.ConditionValue);
if (errorKind != ValidationErrorKind.Success)
{
QuestDialogValidatorError error = new QuestDialogValidatorError
{
TaskIndex = taskIndex,
Kind = errorKind,
SequenceId = sequenceId,
SequenceActionIndex = actionIdex,
};
errors.Add(error);
}
}
else if(sequenceAction.Talker == DialogTalker.Npc && sequenceAction.NpcAction != 0)
{
var errorKind = _ugqMetadata.isValidNpcActionId(sequenceAction.NpcAction);
if (errorKind != ValidationErrorKind.Success)
{
QuestDialogValidatorError error = new QuestDialogValidatorError
{
TaskIndex = taskIndex,
Kind = errorKind,
SequenceId = sequenceId,
SequenceActionIndex = actionIdex,
};
errors.Add(error);
}
}
if (sequenceId != -1)
{
if (sequenceIds.Any(x => x == sequenceId) == false)
{
QuestDialogValidatorError error = new QuestDialogValidatorError
{
TaskIndex = taskIndex,
Kind = ValidationErrorKind.InvalidDialogNextSequence,
SequenceId = sequenceId,
SequenceActionIndex = actionIdex,
};
errors.Add(error);
}
}
}
void ValidateQuestDialogSequence(int taskIndex, List<int> sequenceIds, DialogSequenceEntity sequence, List<ValidationError> errors)
{
foreach (var (index, action) in sequence.Actions.Select((action, index) => (index, action)))
{
ValidateQuestDialogSequenceAction(taskIndex, sequenceIds, sequence.SequenceId, index, action, errors);
}
int playerTalkerCount = 0;
int npcTalkerCount = 0;
bool invalidTalkerOrder = false;
foreach (var (index, action) in sequence.Actions.Select((action, index) => (index, action)))
{
if (action.Talker == DialogTalker.Player)
{
playerTalkerCount++;
}
else if (action.Talker == DialogTalker.Npc)
{
// Npc<70>ε<EFBFBD>, playerTalkerCount<6E><74> 0<><30><EFBFBD><EFBFBD> ũ<>ٸ<EFBFBD>, Player<65>ڿ<EFBFBD> Npc<70><63> <20><><EFBFBD>Դٴ<D4B4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>
if (playerTalkerCount > 0)
invalidTalkerOrder = true;
npcTalkerCount++;
}
}
if (playerTalkerCount < 1)
{
QuestDialogValidatorError error = new QuestDialogValidatorError
{
TaskIndex = taskIndex,
Kind = ValidationErrorKind.NotSetPlayerTalker,
SequenceId = sequence.SequenceId,
};
}
if (invalidTalkerOrder == true)
{
QuestDialogValidatorError error = new QuestDialogValidatorError
{
TaskIndex = taskIndex,
Kind = ValidationErrorKind.InvalidTalkerOrder,
SequenceId = sequence.SequenceId,
};
}
}
void ValidateQuestDialog(int taskIndex, QuestDialogEntity questDialog, List<ValidationError> errors)
{
var sequenceIds = questDialog.Sequences.Select(x => x.SequenceId).ToList();
List<int> npcActionIds = new();
var dialogActions = questDialog.Sequences.Select(x => x.Actions).ToList();
foreach(var item in dialogActions)
npcActionIds.AddRange(item.Select(x => x.NpcAction).ToList());
bool hasEnd = false;
foreach (var sequence in questDialog.Sequences)
{
ValidateQuestDialogSequence(taskIndex, sequenceIds, sequence, errors);
foreach (var action in sequence.Actions)
{
if(action.NextSequence == -1)
hasEnd = true;
}
}
if (hasEnd == false)
{
QuestDialogValidatorError error = new QuestDialogValidatorError
{
TaskIndex = taskIndex,
Kind = ValidationErrorKind.DontHaveEndSequence,
};
errors.Add(error);
}
}
}