초기커밋

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,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Google.Protobuf.WellKnownTypes;
using ServerCore; using ServerBase;
namespace ServerCommon
{
public class ClaimMetaData
{
public EEventType EventType;
public MetaAssets.ClaimType ClaimType;
public int ClaimId = 0;
public DateTime StartTime = new();
public DateTime EndTime = new();
public SortedDictionary<int, ClaimRewardDetail> DetailInfo = new();
//public EventSpecInfo SpecInfo = new EventSpecInfo();
public ClaimMetaData(EEventType eventType, int claimId, MetaAssets.ClaimType claimType)
{
EventType = eventType;
ClaimId = claimId;
ClaimType = claimType;
//SpecInfo.Conditions = new();
//EventInvokerCondition eventInvokerCondition = new EventInvokerCondition();
//eventInvokerCondition.invokerType = EInvokerType.TIMER;
//eventInvokerCondition.invokerAction = EInvokerActionType.CHECK;
//eventInvokerCondition.conditionSequence = 1;
//eventInvokerCondition.paramKeyValues = new();
//EventParamKeyValue eventParamKeyValue = new(EInvokerParamType.ElapsedTime, EInvokerParamType.ElapsedTime.ToString());
//eventInvokerCondition.paramKeyValues.Add(eventParamKeyValue);
//SpecInfo.Conditions.Add(eventInvokerCondition);
}
public int GetMetaId()
{
return ClaimId;
}
public bool SetMetaId(int value)
{
ClaimId = value;
return true;
}
public string toBasicString() => $"{this.getTypeName()}: {ClaimId}-{ClaimType}-{EventType}";
}
public class ClaimRewardDetail
{
public int Idx;
public int RewardGroupId;
public long CoolTime;
public bool isSpecialReward;
}
}

View File

@@ -0,0 +1,135 @@
using Newtonsoft.Json;
using ServerCore;
using ServerBase;
namespace ServerCommon;
public class Anchor
{
[JsonProperty("Type")]
public string Type = string.Empty;
[JsonProperty("GUID")]
public string GUID = string.Empty;
[JsonProperty("TableID")]
public int TableID = 0;
[JsonProperty("EntityGuid")]
public string EntityGuid = string.Empty;
[JsonProperty("Position")]
public Position Position = new();
[JsonProperty("Rotation")]
public Rotation Rotation = new();
[JsonProperty("EditorName")]
public string EditorName = string.Empty;
[JsonProperty("MannequinItems")]
public List<int> MannequinItems = new();
}
public class Building
{
[JsonProperty("BuildingName")]
public string BuildingName = string.Empty;
[JsonProperty("BuildingGUID")]
public string GUID = string.Empty;
[JsonProperty("BuildingPosition")]
public Position Position = new();
[JsonProperty("BuildingROT")]
public Rotation Rotation = new();
}
public class Room
{
[JsonProperty("InstanceRoomFileName")]
public string RoomName = string.Empty;
[JsonProperty("RoomGUID")]
public string GUID = string.Empty;
[JsonProperty("RoomPOS")]
public ServerCore.Position Position = new();
[JsonProperty("RoomROT")]
public ServerCore.Rotation Rotation = new();
}
public class MapData
{
[JsonProperty("LandNames")]
public List<string> LandNames = new();
[JsonProperty("BuildingDatas")]
public List<Building> BuildingDatas = new();
[JsonProperty("RoomDatas")]
public List<Room> RoomDatas = new();
[JsonProperty("Anchors")]
public List<Anchor> Anchors = new();
[JsonProperty("Type")]
public string Type = string.Empty;
[JsonProperty("GUID")]
public string GUID = string.Empty;
[JsonProperty("TableID")]
public int TableID = 0;
[JsonProperty("Position")]
public ServerCore.Position Position = new();
[JsonProperty("Rotation")]
public ServerCore.Rotation Rotation = new();
[JsonProperty("Min")]
public ServerCore.Position Min = new();
[JsonProperty("Max")]
public ServerCore.Position Max = new();
// Load 시 MetaTable 과 비교 하여 값을 넣는다
public MapFileType MapFileType = MapFileType.None;
public int MapMetaId = 0;
}
public class Framework
{
[JsonProperty("tableid")]
public int tableid = 0;
[JsonProperty("Floor")]
public int Floor = 0;
[JsonProperty("Position")]
public ServerCore.Position Position = new();
[JsonProperty("Rotation")]
public ServerCore.Rotation Rotation = new();
}
public class MyhomeMapData
{
[JsonProperty("roomtype")]
public int roomtype = 0;
[JsonProperty("Frameworks")]
public List<Framework> Frameworks = new();
[JsonProperty("Anchors")]
public List<Anchor> Anchors = new();
}

View File

@@ -0,0 +1,176 @@
using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
using ServerCore;
using ServerBase;
namespace ServerCommon;
public class MapDataTable
{
private static readonly MapDataTable _instance = new();
static MapDataTable() { }
private MapDataTable() { }
public static MapDataTable Instance { get { return _instance; } }
Dictionary<string, string> m_map_paths = new();
Dictionary<string, MapData> m_mapdatas = new();
Dictionary<string, Anchor> m_anchors = new();
public bool Load()
{
string mapDataPath = Path.GetFullPath("resource/map", Environment.CurrentDirectory);
var all_map_paths = Directory.GetFiles(mapDataPath, "*.*", SearchOption.AllDirectories);
foreach (var path in all_map_paths)
{
if (!m_map_paths.TryAdd(Path.GetFileName(path), path))
{
m_map_paths.TryGetValue(Path.GetFileName(path), out var duplicatePath);
var duplicate_sub_path = duplicatePath?.Replace(mapDataPath, "");
var sub_path = path.Replace(mapDataPath, "");
Log.getLogger().error($"duplicate map name:{Path.GetFileName(path)} path_1:{duplicate_sub_path} path_2:{sub_path}");
}
}
foreach (var data in MetaData.Instance._WorldMetaTable.Values)
{
if (string.IsNullOrEmpty(data.MapPath))
continue;
if (!LoadMapFile(data.MapPath))
continue;
if (m_mapdatas.TryGetValue(data.MapPath, out var mapData))
{
mapData.MapFileType = MapFileType.World;
mapData.MapMetaId = data.Id;
}
}
foreach (var data in MetaData.Instance._LandTable.Values)
{
if (string.IsNullOrEmpty(data.LandFile))
continue;
if (!LoadMapFile(data.LandFile))
continue;
if (m_mapdatas.TryGetValue(data.LandFile, out var mapData))
{
mapData.MapFileType = MapFileType.Land;
mapData.MapMetaId = data.LandId;
}
}
foreach (var data in MetaData.Instance._BuildingTable.Values)
{
if (string.IsNullOrEmpty(data.BuildingFile))
continue;
if (!LoadMapFile(data.BuildingFile))
continue;
if (m_mapdatas.TryGetValue(data.BuildingFile, out var mapData))
{
mapData.MapFileType = MapFileType.Building;
mapData.MapMetaId = data.BuildingId;
}
}
foreach (var data in MetaData.Instance._IndunTable.Values)
{
if (string.IsNullOrEmpty(data.RoomFile))
continue;
if (!LoadMapFile(data.RoomFile))
continue;
if (m_mapdatas.TryGetValue(data.RoomFile, out var mapData))
{
mapData.MapFileType = MapFileType.Instance;
mapData.MapMetaId = data.Id;
}
}
return true;
}
bool LoadMapFile(string fileName)
{
try
{
if (!m_map_paths.TryGetValue(fileName, out var filePath))
{
Log.getLogger().warn($"Not Found Map Path !!! : fileName:{fileName}");
return false;
}
if (!File.Exists(filePath))
{
Log.getLogger().warn($"File is not Exist !!! : filePath:{filePath}");
return false;
}
var json = File.ReadAllText(filePath);
var list = JsonConvert.DeserializeObject<List<MapData>>(json);
if (list == null)
{
Log.getLogger().error($"Failed to DeserializeObject() !!! : fileName:{fileName}");
return false;
}
foreach (var one in list)
{
m_mapdatas.TryAdd(fileName, one);
foreach (var anchor in one.Anchors)
{
m_anchors.TryAdd(anchor.GUID, anchor);
}
}
return true;
}
catch (Exception e)
{
Log.getLogger().fatal($"Failed to LoadMapFile() !!! : Exception:{e}");
return false;
}
}
public bool getMapData(string mapFileName, [MaybeNullWhen(false)] out MapData mapData)
{
return m_mapdatas.TryGetValue(mapFileName, out mapData);
}
public bool getAnchor(string anchorGuid, [MaybeNullWhen(false)] out Anchor anchor)
{
return m_anchors.TryGetValue(anchorGuid, out anchor);
}
public string GetRoomStartPosAnchorGuid(string mapFilename)
{
if (!m_mapdatas.TryGetValue(mapFilename, out var mapData))
{
return string.Empty;
}
foreach (var anchor in mapData.Anchors)
{
if (anchor.Type == "AT_StartPos")
return anchor.GUID;
}
return string.Empty;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,580 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Amazon.Runtime.Internal.Util;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace MetaAssets;
public class CustomStringEnumConverter : StringEnumConverter
{
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
try
{
if (reader.TokenType == JsonToken.String)
{
string? enumText = reader.Value?.ToString();
if (string.IsNullOrEmpty(enumText))
enumText = "None";
return Enum.Parse(objectType, enumText!, true);
}
}
catch (Exception ex)
{
throw new Exception($"Error converting value {reader.Value?.ToString()} to type '{objectType}'." , ex);
}
// we don't actually expect to get here.
throw new Exception($"Unexpected token {reader.TokenType} when parsing enum.");
}
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ESeasonPassType
{
None = 0,
Free = 1,
Charged = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EActionType
{
NONE = 0,
SINGLE = 1,
MULTI = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum TaxiType
{
NONE = 0,
INSTANCE = 1,
WAYPOINT = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ERequirementItemType
{
None = 0,
OWNS = 1,
EQUIP = 2,
USE = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ERequirementQuestType
{
None = 0,
ING = 1,
COMPLETED = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EQuestType
{
NONE = 0,
EPIC = 1,
TUTORIAL = 2,
NORMAL = 3,
UGQ = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EAssignType
{
NONE = 0,
MAIL = 1,
DIALOGUE = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EAssignRequireType
{
NONE = 0,
PlayerInitial = 1,
Quest_Complete = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum OncePeriodRangeType
{
NONE = 0,
Nolimit = 1,
Daily = 2,
Weekly = 3,
Monthly = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum LandType
{
NORMAL = 0,
CONCERT = 1,
FARMING = 2,
PUBLICSHARE = 3,
RENTAL = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EExpireType
{
NONE = 0,
TOOL = 1,
FIXEDTERM = 2,
DELAY = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EItemLargeType
{
TOOL = 0,
EXPENDABLE = 1,
TICKET = 2,
RAND_BOX = 3,
CLOTH = 4,
AVATAR = 5,
PROP = 6,
TATTOO = 7,
BEAUTY = 8,
CURRENCY = 9,
PRODUCT = 10,
SET_BOX = 11,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EItemSmallType
{
HANDMIRROR = 0,
LIGHTSTICK = 1,
FIRECRACKER = 2,
LIGHTSABER = 3,
REGISTER_ITEM_SOCIAL_ACTION = 4,
REGISTER_ITEM_INTERIOR = 5,
SAIYAN_AURA = 6,
TICKET = 7,
RANDOMBOX = 8,
SHIRT = 9,
DRESS = 10,
OUTER = 11,
PANTS = 12,
GLOVES = 13,
RING = 14,
BRACELET = 15,
BAG = 16,
BACKPACK = 17,
CAP = 18,
MASK = 19,
GLASSES = 20,
EARRING = 21,
NECKLACE = 22,
SHOES = 23,
SOCKS = 24,
ANKLET = 25,
OFFICECHAIR = 26,
WALLMOUNTTV = 27,
OUTDOORCHAIR = 28,
TV = 29,
VIGNETTE = 30,
COOKWARE = 31,
KITCHEN_TOOL = 32,
LAPTOP = 33,
OUTDOOR_GOODS = 34,
BED = 35,
DECO = 36,
FURNITURE = 37,
MUSIC = 38,
SHELF_S = 39,
SHELF_L = 40,
SOFA_SINGLE = 41,
SOFA_COUCH = 42,
LIGHT_CEILING = 43,
LIGHT_FLOOR = 44,
LIGHT_TABLE = 45,
LIGHT_PENDENT = 46,
TABLE_S = 47,
TABLE_L = 48,
TABLE_LIVINGROOM = 49,
TABLE_OFFICE = 50,
LEISURE_APPLIANCE = 51,
INDUCTION = 52,
MICROWAVE = 53,
LARGE_APPLIANCE = 54,
COSMETIC = 55,
CHEST = 56,
LEFT_ARM = 57,
RIGHT_ARM = 58,
BACK = 59,
LEFT_LEG = 60,
RIGHT_LEG = 61,
CARTRIDGE = 62,
BUFF_DRINK = 63,
INTERPHONE = 64,
MEGAPHONE = 65,
CURRENCY = 66,
NFTLAND = 67,
SUMMONSTONE = 68,
CRAFTING_CLOTHES = 69,
CRAFTING_FURNITURE = 70,
CRAFTING_COOKING = 71,
BEACON_BODY = 72,
BEACON_ITEM = 73,
RECIPE = 74,
QUEST_ASSIGN = 75,
QUEST_COOLTIME_RESET = 76,
GOLD = 77,
SAPPHIRE = 78,
CALIUM = 79,
RUBY = 80,
BEAM = 81,
PRODUCT = 82,
SPEAKER = 83,
LIGHT_LIMITED = 84,
MUSICPLAYER = 85,
NECKLESS = 86,
SHOULDERBAG = 87,
LANDCERTIFICATE = 88,
SETBOX = 89,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EUGQAction
{
NONE = 0,
NOTUSE = 1,
CLOTH = 2,
FOOD = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ESnapType
{
Wall = 0,
Floor = 1,
Ceiling = 2,
Free = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum AccessType
{
Public = 0,
Item = 1,
Belong = 2,
Season = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum VoiceChatType
{
Normal = 0,
All = 1,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ViewType
{
Basic = 0,
Closure = 1,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ETileType
{
Wall = 0,
Floor = 1,
Ceiling = 2,
Object = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum FacialAnimationType
{
Laugh = 0,
Cry = 1,
Smile = 2,
Sad = 3,
Angry = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ParticlePositionType
{
Head = 0,
Hand_r = 1,
Hand_l = 2,
Spine_03 = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum CategoryType
{
Expression = 0,
Signs = 1,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ERecipeType
{
None = 0,
Basic = 1,
Add = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ECVArithmeticOperation
{
Add = 0,
Sub = 1,
Mul = 2,
Div = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EGenderType
{
MALE = 0,
FEMALE = 1,
ALL = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ERaceType
{
LATINO = 0,
CAUCASIAN = 1,
AFRICAN = 2,
NORTHEASTASIAN = 3,
SOUTHASIAN = 4,
PACIFICISLANDER = 5,
ALL = 6,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ERewardType
{
None = 0,
Currency = 1,
Item = 2,
Gacha = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EBuffCategory
{
None = 0,
NORMAL = 1,
EVENT = 2,
INSTANCE = 3,
TOOL = 4,
WEAR = 5,
}
[JsonConverter(typeof(CustomStringEnumConverter))]
public enum BuffMotionSetType
{
NONE = 0,
STICK = 1,
FOOD = 2,
DRINK = 3,
GUN = 4,
}
[JsonConverter(typeof(CustomStringEnumConverter))]
public enum BuffHandType
{
NONE = 0,
STICK = 1,
GIMBAP = 2,
CUP = 3,
DEFAULT = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum InstanceType
{
LF = 0,
RF = 1,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ItemType
{
DECO = 0,
SIGN = 1,
NPC = 2,
KIOSK = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum WorldAccessType
{
None = 0,
NFT = 1,
Item = 2,
Public = 3,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ClaimType
{
None = 0,
Normal = 1,
Membership = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum WarpType
{
NONE = 0,
ELEVATOR = 1,
FITTINGROOM = 2,
MYHOME = 3,
RETURN = 4,
TAXI = 5,
WORLD = 6,
BeaconCreateRoom = 7,
EDITROOM = 8,
INSTANCE = 9,
BattleRoom = 10
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EConditionSelection
{
USE_STATIC = 0,
USE_SOURCE = 1,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EUGQValueSource
{
NONE = 0,
UGQ_NPC = 1,
CLOTH_ITEM = 2,
UGQ_ITEM = 3,
UGQ_ATTRIBUTE_DEFINITION = 4,
RANGE_1_30 = 5,
UGQ_SOCIAL_ACTION = 6,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ECVToolMotionType
{
STICK = 0,
DRINK = 1,
GUN = 2,
FOOD = 3,
LANTERN = 4,
MICROPHONE = 5,
QUESTCAM = 6,
SMARTCAM = 7,
PHONE = 8,
DEFAULT = 9,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ECVToolHandGripType
{
STICK = 0,
CUP = 1,
GUN = 2,
GIMBAP = 3,
LANTERN = 4,
YELLOWCARD = 5,
MICROPHONE = 6,
QUESTCAM = 7,
SMARTCAM = 8,
DRINK = 9,
CAMERA = 10,
DEFAULT = 11,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ActivateFuncType
{
NONE = 0,
VOICE = 1,
PHOTO = 2,
MUSICBOX = 3,
MUSICPLAYER = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum SizeType
{
NONE = 0,
SMALL = 1,
MEDIUM = 2,
LARGE = 3,
GIANT = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EBuffEndCondition
{
NONE = 0,
ACTIONSTEP = 1,
TRIGGER = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EBuffEndExecution
{
NONE = 0,
GETBUFF = 1,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EditorType
{
NONE = 0,
CALIVERSE = 1,
USER = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EBattleObjectType
{
None = 0,
Weapon = 1,
Pod_Combat = 2,
Pod_Box = 3,
Buff = 4,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ECombatPodType
{
None = 0,
Storage = 1,
Pod = 2,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EPropSmallType
{
None = 0,
Default = 1,
Cooking = 2,
FURNITURE = 3,
CLOTHES = 4,
EXIT = 5,
SHORTCUT = 6,
PLAY = 7,
}

View File

@@ -0,0 +1,17 @@

using ServerBase;
using MetaAssets;
namespace ServerCommon;
public static class AttributeEnchantDataValidator
{
[MetaValidator]
public static void Validate(AttributeEnchantMetaData enchant, ValidatorErrorCollection errors)
{
// 1. Item Id 체크
if(false == CommonValidator.isExistItemId(enchant.ItemID))
errors.add($"Attribute Enchant Data Is Invalid : item id is not exist - {enchant.ItemID}");
}
}

View File

@@ -0,0 +1,36 @@
using MetaAssets;
namespace ServerCommon;
public class CommonValidator
{
public static bool isExistCurrencyId(int currencyId)
{
return MetaData.Instance.Meta.CurrencyMetaTable.CurrencyMetaDataListbyId.ContainsKey(currencyId);
}
public static bool isExistItemId(int itemId)
{
return MetaData.Instance.Meta.ItemMetaTable.ItemMetaDataListbyId.ContainsKey(itemId);
}
public static bool isExistProductGroupId(int id)
{
return MetaData.Instance.Meta.ShopProductMetaTable.ShopProductMetaDataList.Any(shopProduct => shopProduct.Group_Id == id);
}
public static bool isExistBrandById(int id)
{
return MetaData.Instance.Meta.BrandMetaTable.BrandMetaDataListbyId.ContainsKey(id);
}
public static bool isExistBuffById(int buffId)
{
return MetaData.Instance.Meta.BuffMetaTable.BuffMetaDataListbyBuffId.ContainsKey(buffId);
}
public static bool isExistProductId(int id)
{
return MetaData.Instance.Meta.ProductMetaTable.ProductMetaDataListbyId.ContainsKey(id);
}
}

View File

@@ -0,0 +1,18 @@

using ServerBase;
using MetaAssets;
namespace ServerCommon;
public static class InstanceDataValidator
{
[MetaValidator]
public static void Validate(InstanceMetaData instance, ValidatorErrorCollection errors)
{
// 1. access type and id 체크
if(instance.AccessType == AccessType.Item && false == CommonValidator.isExistItemId(instance.AccessId))
errors.add($"Invalid Instance data : access type and id is invalid - AccessType[{instance.AccessType}] AccessId[{instance.AccessId}]");
}
}

View File

@@ -0,0 +1,200 @@
using ServerBase;
using MetaAssets;
namespace ServerCommon;
public static class ItemMetaTableValidator
{
private static Dictionary<EItemLargeType, List<EItemSmallType>> m_LargeTypeAndSmallType { get; set; } = initLargeTypeAndSmallType();
[MetaValidator]
public static void Validate(ItemMetaData item, ValidatorErrorCollection errors)
{
// 1. item worth 체크
if (false == checkItemWorth(item))
errors.add($"Invalid Item : Worth data is invalid - Current => SellPriceType[{item.SellPriceType}], SellId[{item.SellId}] / Buy_Price_Type[{item.Buy_Price_Type}], Buy_id[{item.Buy_id}]");
// 2. tattoo 체크
if (item.TypeLarge == EItemLargeType.TATTOO)
checkTattooValues(item, errors);
// 3. buff_drink 체크
if (item.TypeSmall == EItemSmallType.BUFF_DRINK && false == CommonValidator.isExistBuffById(item.buff_id))
errors.add($"Invalid Item : Buff Drink's buff id is Invalid - Current => BuffId[{item.buff_id}]");
// 4. type_large & type_small 관계성 체크
if(false == checkLargeAndSmallType(item.TypeLarge, item.TypeSmall))
errors.add($"Invalid Item : Large and Small Type is invalid - Current => Large[{item.TypeLarge}] Small[{item.TypeSmall}]");
// 5. expire time check
if (item.ExpireFixedTermStart > item.ExpireFixedTermEnd)
errors.add($"Invalid Item : ExpireFixedTerm Time is Invalid - Current => start[{item.ExpireFixedTermStart}] end[{item.ExpireFixedTermEnd}]");
// 6. brand 체크 : 0이 될 수 있어.
if(item.Brand_ > 0 && false == CommonValidator.isExistBrandById(item.Brand_))
errors.add($"Invalid Item : Brand Id is Invalid - brand [{item.Brand_}]");
}
private static bool checkItemWorth(ItemMetaData item)
{
// 1. Sell 체크
if (item.SellPriceType == ShopBuyType.Currency && false == CommonValidator.isExistCurrencyId(item.SellId))
return false;
if (item.SellPriceType == ShopBuyType.Item && false == CommonValidator.isExistItemId(item.SellId))
return false;
// 2. Buy 체크
if (item.Buy_Price_Type == ShopBuyType.Currency && false == CommonValidator.isExistCurrencyId(item.Buy_id))
return false;
if (item.Buy_Price_Type == ShopBuyType.Item && false == CommonValidator.isExistItemId(item.Buy_id))
return false;
return true;
}
private static void checkTattooValues(ItemMetaData item, ValidatorErrorCollection errors)
{
if (string.IsNullOrEmpty(item.Rarity))
errors.add( "Invalid Item : Tattoo Rarity is invalid");
if (string.IsNullOrEmpty(item.DefaultAttribute))
errors.add( "Invalid Item : Tattoo DefaultAttribute is invalid");
if (string.IsNullOrEmpty(item.AttributeRandomGroupID))
errors.add( "Invalid Item : Tattoo AttributeRandomGroupId is invalid");
if (false == MetaData.Instance.Meta.AttributeDefinitionMetaTable.AttributeDefinitionMetaDataListbyKey.ContainsKey(item.DefaultAttribute))
errors.add( $"Invalid Item : Default Attribute is invalid - [{item.DefaultAttribute}]");
}
private static bool checkLargeAndSmallType(EItemLargeType largeType, EItemSmallType smallType)
{
if (false == m_LargeTypeAndSmallType.TryGetValue(largeType, out var list)) return false;
return list.Contains(smallType);
}
private static Dictionary<EItemLargeType, List<EItemSmallType>> initLargeTypeAndSmallType()
{
var dict = new Dictionary<EItemLargeType, List<EItemSmallType>>();
var smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.COSMETIC);
dict.Add(EItemLargeType.BEAUTY, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.BACKPACK);
smallList.Add(EItemSmallType.BAG);
smallList.Add(EItemSmallType.CAP);
smallList.Add(EItemSmallType.DRESS);
smallList.Add(EItemSmallType.GLASSES);
smallList.Add(EItemSmallType.GLOVES);
smallList.Add(EItemSmallType.MASK);
smallList.Add(EItemSmallType.NECKLACE);
smallList.Add(EItemSmallType.OUTER);
smallList.Add(EItemSmallType.PANTS);
smallList.Add(EItemSmallType.SHIRT);
smallList.Add(EItemSmallType.SHOES);
smallList.Add(EItemSmallType.SHOULDERBAG);
dict.Add(EItemLargeType.CLOTH, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.GOLD);
smallList.Add(EItemSmallType.SAPPHIRE);
smallList.Add(EItemSmallType.CALIUM);
smallList.Add(EItemSmallType.BEAM);
smallList.Add(EItemSmallType.RUBY);
dict.Add(EItemLargeType.CURRENCY, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.BEACON_BODY);
smallList.Add(EItemSmallType.BEACON_ITEM);
smallList.Add(EItemSmallType.BUFF_DRINK);
smallList.Add(EItemSmallType.CARTRIDGE);
smallList.Add(EItemSmallType.MEGAPHONE);
smallList.Add(EItemSmallType.QUEST_ASSIGN);
smallList.Add(EItemSmallType.QUEST_COOLTIME_RESET);
smallList.Add(EItemSmallType.RECIPE);
smallList.Add(EItemSmallType.REGISTER_ITEM_INTERIOR);
smallList.Add(EItemSmallType.REGISTER_ITEM_SOCIAL_ACTION);
smallList.Add(EItemSmallType.SUMMONSTONE);
smallList.Add(EItemSmallType.TICKET);
smallList.Add(EItemSmallType.LANDCERTIFICATE);
dict.Add(EItemLargeType.EXPENDABLE, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.PRODUCT);
dict.Add(EItemLargeType.PRODUCT, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.BED);
smallList.Add(EItemSmallType.COOKWARE);
smallList.Add(EItemSmallType.CRAFTING_CLOTHES);
smallList.Add(EItemSmallType.CRAFTING_COOKING);
smallList.Add(EItemSmallType.CRAFTING_FURNITURE);
smallList.Add(EItemSmallType.DECO);
smallList.Add(EItemSmallType.FURNITURE);
smallList.Add(EItemSmallType.INDUCTION);
smallList.Add(EItemSmallType.INTERPHONE);
smallList.Add(EItemSmallType.LAPTOP);
smallList.Add(EItemSmallType.LARGE_APPLIANCE);
smallList.Add(EItemSmallType.LEISURE_APPLIANCE);
smallList.Add(EItemSmallType.LIGHT_CEILING);
smallList.Add(EItemSmallType.LIGHT_FLOOR);
smallList.Add(EItemSmallType.LIGHT_TABLE);
smallList.Add(EItemSmallType.LIGHT_PENDENT);
smallList.Add(EItemSmallType.LIGHT_LIMITED);
smallList.Add(EItemSmallType.MICROWAVE);
smallList.Add(EItemSmallType.MUSIC);
smallList.Add(EItemSmallType.OFFICECHAIR);
smallList.Add(EItemSmallType.OUTDOOR_GOODS);
smallList.Add(EItemSmallType.OUTDOORCHAIR);
smallList.Add(EItemSmallType.SHELF_L);
smallList.Add(EItemSmallType.SHELF_S);
smallList.Add(EItemSmallType.SOFA_COUCH);
smallList.Add(EItemSmallType.SOFA_SINGLE);
smallList.Add(EItemSmallType.TABLE_L);
smallList.Add(EItemSmallType.TABLE_LIVINGROOM);
smallList.Add(EItemSmallType.TABLE_OFFICE);
smallList.Add(EItemSmallType.TABLE_S);
smallList.Add(EItemSmallType.TV);
smallList.Add(EItemSmallType.VIGNETTE);
smallList.Add(EItemSmallType.WALLMOUNTTV);
smallList.Add(EItemSmallType.SPEAKER);
smallList.Add(EItemSmallType.KITCHEN_TOOL);
dict.Add(EItemLargeType.PROP, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.RANDOMBOX);
dict.Add(EItemLargeType.RAND_BOX, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.BACK);
smallList.Add(EItemSmallType.CHEST);
smallList.Add(EItemSmallType.LEFT_ARM);
smallList.Add(EItemSmallType.LEFT_LEG);
smallList.Add(EItemSmallType.RIGHT_ARM);
smallList.Add(EItemSmallType.RIGHT_LEG);
dict.Add(EItemLargeType.TATTOO, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.TICKET);
dict.Add(EItemLargeType.TICKET, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.LIGHTSTICK);
smallList.Add(EItemSmallType.LIGHTSABER);
smallList.Add(EItemSmallType.MUSICPLAYER);
dict.Add(EItemLargeType.TOOL, smallList);
smallList = new List<EItemSmallType>();
smallList.Add(EItemSmallType.SETBOX);
dict.Add(EItemLargeType.SET_BOX, smallList);
return dict;
}
}

View File

@@ -0,0 +1,218 @@
using System.Collections.Concurrent;
using System.Text;
using Microsoft.Extensions.Primitives;
using ServerCore;
using ServerBase;
namespace ServerCommon;
/*
* QustSript 체크후
* m_event_check_keys, m_function_check_keys 이 두 변수에 데이터가 남아 있으면 안된다.
*/
public class QuestMetaValidateHandler
{
private UInt32 m_quest_id { get; } = 0;
private ConcurrentDictionary<string, int> m_event_checkers { get; } = new();
private ConcurrentDictionary<string, int> m_function_checkers { get; }= new();
public QuestMetaValidateHandler()
{
}
public QuestMetaValidateHandler(UInt32 questId)
{
m_quest_id = questId;
}
//해당 이벤트가 체크되어야햘 항목에 있는지 확인하고 있으면 삭제 처리
public void checkEventTarget(string eventTarget, string eventName, string eventCond1, string eventCond2, string eventCond3)
{
StringBuilder str_builder = new();
if (eventTarget.Equals(EQuestEventTargetType.TASK.ToString()) && eventName.Equals(EQuestEventNameType.ACTIVED.ToString()))
{
str_builder.Append(eventTarget).Append(eventName).Append(eventCond1);
}
else if (eventTarget.Equals(EQuestEventTargetType.TRIGGER.ToString()) && eventName.Equals(EQuestEventNameType.ENTERED.ToString()))
{
str_builder.Append(eventTarget).Append(eventName).Append(eventCond1);
}
else if (eventTarget.Equals(EQuestEventTargetType.DIALOGUE.ToString()) &&
eventName.Equals(EQuestEventNameType.ENDED.ToString()))
{
str_builder.Append(eventTarget).Append(eventName).Append(eventCond1);
}
decreaseEventChecker(str_builder.ToString());
}
//해당 펑션이 체크되어야햘 항목에 있는지 확인하고 있으면 삭제 처리
public void checkFuncTarget(string funcTarget, string funcName, string funcCond1, string funcCond2, string funcCond3)
{
StringBuilder str_builder = new();
if (funcTarget.Equals(EQuestFunctionTargetType.TASK.ToString()) && funcName.Equals(EQuestFunctionNameType.TITLE_UPDATE.ToString()))
{
str_builder.Append(funcTarget).Append(funcName).Append(funcCond1);
}
else if (funcTarget.Equals(EQuestFunctionTargetType.TASK.ToString()) && funcName.Equals(EQuestFunctionNameType.LOCATION.ToString()))
{
str_builder.Append(funcTarget).Append(funcName);
}
else if (funcTarget.Equals(EQuestFunctionTargetType.QUEST.ToString()) && funcName.Equals(EQuestFunctionNameType.COMPLETE.ToString()))
{
str_builder.Append(funcTarget).Append(funcName).Append(funcCond1);
}
decreaseFuncChecker(str_builder.ToString());
}
//해당 이벤트 타겟에 대한 체크항목 생성
//여기에 계속 추가해야한다.
public void makeEventTargetValidator(string eventTarget, string eventName, string eventCond1, string eventCond2, string eventCond3)
{
if (eventTarget.Equals(EQuestEventTargetType.TASK.ToString()) && eventName.Equals(EQuestEventNameType.ACTIVED.ToString()))
{
_ = new QuestValidatorForTaskActived(this, eventCond1);
}
}
//해당 펑션 타겟에 대한 체크항목 생성
//여기에 계속 추가해야 한다.
public void makeFuncTargetValidator(string funcTarget, string funcName, string funcCond1, string funcCond2, string funcCond3)
{
if (funcTarget.Equals(EQuestEventTargetType.TRIGGER.ToString()) && funcName.Equals(EQuestFunctionNameType.SET.ToString()))
{
_ = new QuestValidatorForTriggerSet(this, funcCond1);
}
else if (funcTarget.Equals(EQuestEventTargetType.NPC.ToString()) &&
funcName.Equals(EQuestFunctionNameType.DIALOGUE_SET.ToString()))
{
_ = new QuestValidatorForNpcDialogueSet(this, funcCond2);
}
}
public void addEventChecker(string eventStr)
{
int update_cnt = 0;
if (false == m_event_checkers.TryGetValue(eventStr, out var cnt))
{
update_cnt = 1;
m_event_checkers.TryAdd(eventStr, update_cnt);
}
else
{
update_cnt = ++cnt;
m_event_checkers.AddOrUpdate(eventStr, update_cnt, (s, i) => update_cnt);
}
}
public void decreaseEventChecker(string eventStr)
{
if (m_event_checkers.ContainsKey(eventStr))
{
m_event_checkers.TryGetValue(eventStr, out var cnt);
var update_cnt = --cnt;
if (update_cnt <= 0)
{
m_event_checkers.TryRemove(eventStr, out _);
}
else
{
m_event_checkers.AddOrUpdate(eventStr, update_cnt, (s, i) => update_cnt);
}
}
}
public void addFunctionChecker(string functionStr)
{
int update_cnt = 0;
if (false == m_function_checkers.TryGetValue(functionStr, out var cnt))
{
update_cnt = 1;
m_function_checkers.TryAdd(functionStr, update_cnt);
}
else
{
update_cnt = ++cnt;
m_function_checkers.AddOrUpdate(functionStr, update_cnt, (s, i) => update_cnt);
}
}
public void decreaseFuncChecker(string funcStr)
{
if (m_function_checkers.ContainsKey(funcStr))
{
m_function_checkers.TryGetValue(funcStr, out var cnt);
var update_cnt = --cnt;
if (update_cnt <= 0)
{
m_function_checkers.TryRemove(funcStr, out _);
}
else
{
m_function_checkers.AddOrUpdate(funcStr, update_cnt, (s, i) => update_cnt);
}
}
}
public void remainDataCheck(ValidatorErrorCollection errors)
{
List<ValidattionError> error_list = new();
if (m_event_checkers.Keys.Count > 0)
{
foreach (var checker in m_event_checkers)
{
ValidattionError validation_error = new();
validation_error.Name = "Quest Script Event Validation Error";
validation_error.ArrayIndex = (int)m_quest_id;
validation_error.Message = $"quest : {m_quest_id}, {checker.Key} is not checked, cnt : {checker.Value}";
error_list.Add(validation_error);
}
}
if (m_function_checkers.Keys.Count > 0)
{
foreach (var checker in m_function_checkers)
{
ValidattionError validation_error = new();
validation_error.Name = "Quest Script Func Validation Error";
validation_error.ArrayIndex = (int)m_quest_id;
validation_error.Message = $"quest : {m_quest_id}, {checker.Key} is not checked, cnt : {checker.Value}";
error_list.Add(validation_error);
}
}
if (error_list.Count > 0)
{
//원래 검증 완료하면 여기에 추가를 해서 서버가 안뜨게 해야 되는게 맞는데
//지금 엑섹을 만들었다 지우면서 발생한 쓰레기 json이 퀘스트로 등록이 되는 상황이라 이런경우 어떠허게 처리해야될지 정리후에
//errors 로 넘긴다
//그 전까진 error log만 남긴다.
//errors.Errors.TryAdd("Quest Script Error", error_list);
foreach (var error in error_list)
{
Log.getLogger().warn($"[ Quest : {m_quest_id}] Script Validation Error : {error.Message}");
}
}
}
}

View File

@@ -0,0 +1,16 @@

namespace ServerCommon;
public abstract class QuestScriptValidatorBase : IQuestScriptValidator
{
protected QuestMetaValidateHandler m_handler { get; set; } = new();
public QuestScriptValidatorBase(QuestMetaValidateHandler handler)
{
m_handler = handler;
}
public abstract void init();
}

View File

@@ -0,0 +1,47 @@
using System.Text;
using Microsoft.Extensions.Primitives;
using ServerCore;
using ServerBase;
namespace ServerCommon;
/*
* Rule
* TASK, ACTIVED 1
* QUEST, COMPLETE (questId) 는 무조건 존재해야 한다.
*
*/
public class QuestValidatorForMustHave : QuestScriptValidatorBase
{
private UInt32 m_quest_id = 0;
public QuestValidatorForMustHave(QuestMetaValidateHandler handler, UInt32 questId) : base(handler)
{
m_quest_id = questId;
init();
}
public override void init()
{
StringBuilder str_builder_task = new();
str_builder_task
.Append(EQuestEventTargetType.TASK.ToString())
.Append(EQuestEventNameType.ACTIVED.ToString())
.Append("1");
m_handler.addEventChecker(str_builder_task.ToString());
StringBuilder str_builder_quest = new();
str_builder_quest
.Append(EQuestFunctionTargetType.QUEST.ToString())
.Append(EQuestFunctionNameType.COMPLETE.ToString())
.Append(m_quest_id.ToString());
m_handler.addFunctionChecker(str_builder_quest.ToString());
}
}

View File

@@ -0,0 +1,28 @@
using System.Text;
using Google.Protobuf.WellKnownTypes;
namespace ServerCommon;
public class QuestValidatorForNpcDialogueSet : QuestScriptValidatorBase
{
private string m_func_cond2 = string.Empty;
public QuestValidatorForNpcDialogueSet(QuestMetaValidateHandler handler, string funcCond2) : base(handler)
{
m_func_cond2 = funcCond2;
init();
}
public override void init()
{
StringBuilder dialogue_ended = new();
dialogue_ended.Append(EQuestEventTargetType.DIALOGUE.ToString()).Append(EQuestEventNameType.ENDED.ToString())
.Append(m_func_cond2);
m_handler.addEventChecker(dialogue_ended.ToString());
}
}

View File

@@ -0,0 +1,48 @@
using System.Text;
using Microsoft.Extensions.Primitives;
using ServerCore;
using ServerBase;
namespace ServerCommon;
/*
* TASK, ACTIVED 가 있으면
* TASK, TITLA_UPDATE, (TASKID)
* TASK, LOCATION
* 필수
*
*/
public class QuestValidatorForTaskActived : QuestScriptValidatorBase
{
private string m_event_cond1 = string.Empty;
public QuestValidatorForTaskActived(QuestMetaValidateHandler handler, string eventCond1) : base(handler)
{
m_event_cond1 = eventCond1;
init();
}
public override void init()
{
StringBuilder title_update = new();
title_update
.Append(EQuestFunctionTargetType.TASK.ToString())
.Append(EQuestFunctionNameType.TITLE_UPDATE.ToString())
.Append(m_event_cond1);
m_handler.addFunctionChecker(title_update.ToString());
// StringBuilder location = new();
// location
// .Append(EQuestFunctionTargetType.TASK.ToString())
// .Append(EQuestFunctionNameType.LOCATION.ToString());
// m_handler.addFunctionChecker(location.ToString());
}
}

View File

@@ -0,0 +1,24 @@
using System.Text;
namespace ServerCommon;
public class QuestValidatorForTriggerSet: QuestScriptValidatorBase
{
private string m_func_cond1 = string.Empty;
public QuestValidatorForTriggerSet(QuestMetaValidateHandler handler, string funcCond1) : base(handler)
{
m_func_cond1 = funcCond1;
init();
}
public override void init()
{
StringBuilder trigger_entered = new();
trigger_entered.Append(EQuestEventTargetType.TRIGGER.ToString()).Append(EQuestEventNameType.ENTERED.ToString())
.Append(m_func_cond1);
m_handler.addEventChecker(trigger_entered.ToString());
}
}

View File

@@ -0,0 +1,74 @@
using System.Text;
using Microsoft.IdentityModel.Tokens;
using ServerCore;
using ServerBase;
using MetaAssets;
namespace ServerCommon;
public static class QuestScriptMetaTableValidator
{
[MetaValidator]
public static void Validate((uint questId, Dictionary<Int32 , MetaAssets.QuestScriptMetaData> questScript) item, ValidatorErrorCollection errors)
{
QuestMetaValidateHandler handler = new(item.questId);
//퀘스트 스크립트가 무조건 가지고 있어야 하는 항목
_ = new QuestValidatorForMustHave(handler, item.questId);
// if (item.questId == 100)
// {
// Log.getLogger().info($"QuestScriptValidation start questId : {item.questId}");
// }
foreach(var line in item.questScript.Values)
{
string event_target = line.EventTarget;
string event_name = line.Event;
string event_cond_1 = line.EventCondition1;
string event_cond_2 = line.EventCondition2;
string event_cond_3 = line.EventCondition3;
if (false == event_target.isNullOrWhiteSpace())
{
handler.checkEventTarget(event_target, event_name, event_cond_1, event_cond_2, event_cond_3);
handler.makeEventTargetValidator(event_target, event_name, event_cond_1, event_cond_2, event_cond_3);
}
string func_target = line.FunctionTarget;
string func_name = line.Function;
string func_cond_1 = line.FunctionCondition1;
string func_cond_2 = line.FunctionCondition2;
string func_cond_3 = line.FunctionCondition3;
if (false == func_target.isNullOrWhiteSpace())
{
handler.checkFuncTarget(func_target, func_name, func_cond_1, func_cond_2, func_cond_3);
handler.makeFuncTargetValidator(func_target, func_name, func_cond_1, func_cond_2, func_cond_3);
}
}
handler.remainDataCheck(errors);
}
}

View File

@@ -0,0 +1,39 @@

using ServerBase;
using MetaAssets;
namespace ServerCommon;
public static class ShopValidator
{
[MetaValidator]
public static void Validate(ShopMetaData shop, ValidatorErrorCollection errors)
{
// 1. resetTime
if(shop.ResetTime <= 0)
errors.add($"Invalid shop : reset time is invalid [{shop.ResetTime}]");
// 2. product group
if(false == CommonValidator.isExistProductGroupId(shop.ShopProduct_Group_Id))
errors.add($"Invalid shop : product group id is invalid [{shop.ShopProduct_Group_Id}]");
}
[MetaValidator]
public static void Validate(ShopProductMetaData shopProduct, ValidatorErrorCollection errors)
{
// 1. Buy 정보 체크
if(shopProduct.Buy_Price_Type == ShopBuyType.Currency && false == CommonValidator.isExistCurrencyId(shopProduct.Buy_Id))
errors.add($"Invalid shop product : buy currency type is invalid - [{shopProduct.Buy_Id}]");
if(shopProduct.Buy_Price_Type == ShopBuyType.Item && false == CommonValidator.isExistItemId(shopProduct.Buy_Id))
errors.add($"Invalid shop product : buy item id is not exist - [{shopProduct.Buy_Id}]");
// 2. Product 정보 체크
if(shopProduct.ProductData.Currency != null && false == CommonValidator.isExistCurrencyId(shopProduct.ProductData.Currency.Id))
errors.add($"Invalid shop product : product currency type is invalid - [{shopProduct.ProductData.Currency.Id}]");
if(shopProduct.ProductData.Item != null && false == CommonValidator.isExistItemId(shopProduct.ProductData.Item.Id))
errors.add($"Invalid shop product : product item id is not exist - [{shopProduct.ProductData.Item.Id}]");
}
}

View File

@@ -0,0 +1,39 @@

using ServerBase;
using MetaAssets;
namespace ServerCommon;
public class MetaTableValidator
{
public void validate(ValidatorErrorCollection errors)
{
MetaValidator validator = new MetaValidator();
var ins = MetaData.Instance;
// 1. item
validator.validate(ins.Meta.ItemMetaTable.ItemMetaDataList, errors);
// 2. quest script
validator.validate(ins._QuestScriptMetaTable.Select(x => (x.Key, x.Value)).ToList().AsReadOnly(), errors);
// 3. shop
validator.validate(ins.Meta.ShopMetaTable.ShopMetaDataList, errors);
// 4. shop product
validator.validate(ins.Meta.ShopProductMetaTable.ShopProductMetaDataList, errors);
// 5. instance data
validator.validate(ins.Meta.InstanceMetaTable.InstanceMetaDataList, errors);
// 6. attribute enchant data
validator.validate(ins.Meta.AttributeEnchantMetaTable.AttributeEnchantMetaDataList, errors);
// 검증할 데이터 계속 추가
// ...
}
}

View File

@@ -0,0 +1,242 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MetaAssets;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace ServerCommon
{
[JsonConverter(typeof(StringEnumConverter))]
public enum EQuestEventTargetType
{
NONE = 0,
AVATARPROFILE = 1,
BEACONDIALOGUE,
BUFF,
CHAIR,
CHANNEL,
CHAT,
CONCERT,
COSTUME,
COUNTER, //쓸지 안쓸지 모르겠는데?
CRAFTING,
CUTSCENE,
DIALOGUE,
DRESSROOM,
FARMING,
FRIEND,
GUI,
INSTANCE,
INTERIORMODE,
ITEM,
MAIL,
MANNEQUIN,
MOVEMENT,
MYHOME,
NPC,
PARTY,
PROP,
QUEST,
RENTAL,
REWARD,
SOCIALACTION,
SPECIALGUIDE,
TASK,
TATTOO,
TAXI,
TOOL,
TRIGGER,
TIMER,
TPS,
UGQ,
VIDEO,
WAITING,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EQuestEventNameType
{
NONE = 0,
ACTIVED,
ADDED ,
ARRIVED,
BOUGHT,
CHANGED,
COMPLETED,
CONVERSIONED,
DELETED,
EDITED,
ENDED,
ENHANCED,
EQUIPED,
EXITED,
ENTERED,
JUMP,
MAX,
PICTURED,
POPUP,
RECEIVED,
REGISTERED,
REQUESTED,
SENDED,
SOLD,
SPRINT,
STARTED,
STOPPED,
SWITCHED,
USED,
VISITED,
PLAYERKILL,
FEVER,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EQuestFunctionTargetType
{
NONE = 0,
CONCERT,
COUNTER,
CUTSCENE,
DIALOGUE,
DRESSROOM,
ELEVATOR,
FRIEND,
GUI,
GUIDE,
INSTANCE,
INVENTORY,
ITEM,
MAIL,
MAINMENU,
MAP,
MYHOME,
NPC,
PARTY,
PROP,
QUEST,
REWARD,
SHOP,
SOCIALACTION,
SPECIALGUIDE,
TASK,
TAXI,
TOOL,
TRIGGER,
WARP,
BUFF,
TIMER,
VIDEO,
PARALLEL,
WAITING,
}
[JsonConverter(typeof(StringEnumConverter))]
public enum EQuestFunctionNameType
{
NONE = 0,
ACTIVE = 1,
ARRIVE = 2,
ASSIGN = 3,
CHANGE = 4,
COMPLETE = 5,
DECREASE = 6,
DELETE = 7,
DIALOGUE_CLEAR = 8,
DIALOGUE_SET = 9,
ENTER = 10,
EXIT = 11,
GIVE = 12,
INVISIBLE = 13,
INCREASE = 14,
LOCATION = 15,
POPUP = 16,
PLAY = 17,
SET = 18,
START = 19,
SWITCH = 20,
TELEPORT = 21,
TITLE_UPDATE = 22,
USE = 23,
}
public class QuestBaseInfo
{
public UInt32 QuestId { get; set; }
public UInt32 QuestRevision { get; set; } = 0;
public UgqStateType UgqState { get; set; } = UgqStateType.None;
public string QuestType { get; set; } = string.Empty;
public bool Reveal { get; set; }
public string AssignType { get; set; } = string.Empty;
public string RequirementType { get; set; } = string.Empty;
public UInt32 RequirementValue { get; set; }
public OncePeriodRangeType OncePeriodRangeType { get; set; } = OncePeriodRangeType.NONE;
public bool NormalPoolActive { get; set; }
public bool ForceAccept { get; set; }
public int RewardGroupId { get; set; }
public string Dialogue { get; set; } = string.Empty;
public string DialogueResult { get; set; } = string.Empty;
public List<UInt32> AssignableQuestsAfterEnd { get; set; } = new();
//public int firstTaskIdx { get; set; } //24-06-19 개선을 위해 주석 처리
//public int firstTaskNum { get; set; } 24-06-19 개선을 위해 주석 처리
public Dictionary<int, QuestTaskGroup> QuestTaskGroupList { get; set; } = new();
}
public class QuestTaskGroup
{
public int TaskNum { get; set; }
//public int NextTaskNum { get; set; } 24-06-19 개선을 위해 주석 처리
//public int NextTaskIdx { get; set; } 24-06-19 개선을 위해 주석 처리
public bool HasCounter { get; set; }
public int MinCounter { get; set; }
public int MaxCounter { get; set; }
public bool HasTimer { get; set; }
public long RemainTime { get; set; }
public bool HasAssignableQuest { get; set; } = false;
public List<UInt32> AssignableQuestIds { get; set; } = new();
public bool IsParallel { get; set; }
//public Dictionary<int, QuestEventInfo> QuestEventGroup { get; set; } = new(); //24-06-19 개선 가능한지 확인해볼것 이거 필요한지 모르겟다. 나중에 다시확인 해볼것
public Dictionary<string, QuestEventInfo> QuestEventGroupByEventString { get; set; } = new(); //<eventstring, eventInfo>
public List<string> EventStringList { get; set; } = new();
}
public class QuestEventInfo
{
public int EventIdx { get; set; }
public string EventTarget { get; set; } = string.Empty;
public string EventName { get; set; } = string.Empty;
public string EventCondition1 { get; set; } = string.Empty;
public string EventCondition2 { get; set; } = string.Empty;
public string EventCondition3 { get; set; } = string.Empty;
public List<QuestEventFunction> QuestEventFunctionList { get; set; } = new();
}
public class QuestEventFunction
{
public int Idx { get; set; } //24-06-19 이게 필요한가??
public string FunctionTarget { get; set; } = string.Empty;
public string FunctionName { get; set; } = string.Empty;
public string FunctionCondition1 { get; set; } = string.Empty;
public string FunctionCondition2 { get; set; } = string.Empty;
public string FunctionCondition3 { get; set; } = string.Empty;
public QuestEventFunction()
{
}
}
}