259 lines
7.3 KiB
C#
259 lines
7.3 KiB
C#
using System.Collections.Concurrent;
|
|
using MetaAssets;
|
|
using ServerBase;
|
|
using ServerCommon;
|
|
|
|
namespace BrokerApiCore;
|
|
public class BrokerMetaTable
|
|
{
|
|
public string Version { get; private set; }
|
|
private readonly MetaTable m_meta_table = new MetaTable();
|
|
|
|
public ProductMetaTable ProductMetaTable => m_meta_table.ProductMetaTable;
|
|
|
|
// TODO: PlanetItemExchangePolicyMetaTable를 PlanetItemExchangePolicyTable로 이름 변경
|
|
public PlanetItemExchangePolicyMetaTable PlanetItemExchangePolicyMetaTable => m_meta_table.PlanetItemExchangePolicyMetaTable;
|
|
public SystemMailMetaTable SystemMailMetaTable => m_meta_table.SystemMailMetaTable;
|
|
public ItemMetaTable ItemMetaTable => m_meta_table.ItemMetaTable;
|
|
public TextStringMetaTable TextStringMetaTable => m_meta_table.TextStringMetaTable;
|
|
|
|
public BrokerMetaTable(MetaTable? source = null, string? versionName = null)
|
|
{
|
|
if (source != null)
|
|
{
|
|
m_meta_table = source;
|
|
Version = versionName ?? Guid.NewGuid().ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
public class BrokerApiMetaLoader : IDisposable
|
|
{
|
|
readonly string m_input_path = "resource/meta";
|
|
|
|
// 스레드 세이프한 딕셔너리로 변경
|
|
private readonly ConcurrentDictionary<string, BrokerMetaTable> m_meta_tables =
|
|
new ConcurrentDictionary<string, BrokerMetaTable>();
|
|
|
|
// 더 세밀한 제어가 필요한 경우를 위한 ReaderWriterLockSlim 추가
|
|
private readonly ReaderWriterLockSlim m_lock = new ReaderWriterLockSlim();
|
|
|
|
// 기본 메타테이블 캐싱
|
|
private BrokerMetaTable m_default_meta_table;
|
|
|
|
public Result load(string? dataPath = null)
|
|
{
|
|
try
|
|
{
|
|
m_lock.EnterWriteLock();
|
|
|
|
// 기본 메타 테이블 로드
|
|
var (result, meta_table) = loadMetaData(dataPath);
|
|
if (result.isFail() || meta_table == null)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if (m_meta_tables.TryAdd(meta_table.Version, meta_table))
|
|
{
|
|
m_default_meta_table = meta_table;
|
|
}
|
|
return result;
|
|
}
|
|
finally
|
|
{
|
|
m_lock.ExitWriteLock();
|
|
}
|
|
}
|
|
|
|
private (Result, BrokerMetaTable?) loadMetaData(string? dataPath = null, string? versionName = null)
|
|
{
|
|
var result = new Result();
|
|
var input_path = dataPath ?? m_input_path;
|
|
try
|
|
{
|
|
var full_path = Path.GetFullPath(input_path, Environment.CurrentDirectory);
|
|
if (!Directory.Exists(full_path))
|
|
{
|
|
full_path = Path.GetFullPath(input_path, AppContext.BaseDirectory);
|
|
if (!Directory.Exists(full_path))
|
|
{
|
|
result.setFail(ServerErrorCode.MetaDataLoadFailed, $"Meta data path not found: {input_path}");
|
|
return (result, null);
|
|
}
|
|
}
|
|
|
|
var meta_table = new MetaTable();
|
|
meta_table.loadForBrokerApi(full_path);
|
|
|
|
var errors = new ValidatorErrorCollection();
|
|
foreach (var data in meta_table.PlanetItemExchangePolicyMetaTable.PlanetItemExchangePolicyDataList)
|
|
{
|
|
validate(data, meta_table, errors);
|
|
}
|
|
if (errors.HasError)
|
|
{
|
|
errors.log();
|
|
}
|
|
|
|
//TODO: ProductMetaTable, SystemMailMetaTable, ItemMetaTable 에 대한 검사도 필요하다.
|
|
var broker_meta_table = new BrokerMetaTable(meta_table, versionName);
|
|
return (result, broker_meta_table);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result.setFail(ServerErrorCode.MetaDataLoadFailed, $"Meta data load failed => {ex.Message}");
|
|
}
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
public BrokerMetaTable getMetaTable(string? versionName = null!)
|
|
{
|
|
try
|
|
{
|
|
m_lock.EnterReadLock();
|
|
|
|
if (string.IsNullOrEmpty(versionName) || versionName == "default")
|
|
{
|
|
return m_default_meta_table;
|
|
}
|
|
|
|
return m_meta_tables.GetValueOrDefault(versionName, m_default_meta_table);
|
|
|
|
// 요청된 버전이 없으면 기본 메타테이블 반환
|
|
}
|
|
finally
|
|
{
|
|
m_lock.ExitReadLock();
|
|
}
|
|
}
|
|
|
|
private ValidatorErrorCollection validate(PlanetItemExchangePolicyMetaData planetItemExchange, MetaTable metaTable, ValidatorErrorCollection errors)
|
|
{
|
|
checkValidCaliverseItem(planetItemExchange);
|
|
checkValidPlanetItem(planetItemExchange);
|
|
return errors;
|
|
|
|
void checkValidPlanetItem(PlanetItemExchangePolicyMetaData data)
|
|
{
|
|
var planet_item_type = toEnum(data.PlanetItemType, PlanetItemType.None);
|
|
switch (planet_item_type)
|
|
{
|
|
case PlanetItemType.Igm26Currency:
|
|
{
|
|
var currency_type = toEnum(data.PlanetItemId, PlanetCurrencyType.None);
|
|
if (currency_type == PlanetCurrencyType.None)
|
|
{
|
|
addError(nameof(data.PlanetItemId),
|
|
$"Planet 화폐 타입이 잘못되었습니다 => PlanetItemId:{data.PlanetItemId}");
|
|
}
|
|
|
|
// if (data.PlanetItemAmount >= 0)
|
|
// {
|
|
// // 재화는 차감만 가능
|
|
// addError(nameof(data.PlanetItemAmount),
|
|
// $"Planet 화폐 수량은 양수 합니다 => PlanetItemAmount:{data.PlanetItemAmount}");
|
|
// }
|
|
|
|
break;
|
|
}
|
|
case PlanetItemType.Igm26Quest:
|
|
break;
|
|
case PlanetItemType.None:
|
|
default:
|
|
addError(nameof(data.PlanetItemId),
|
|
$"Planet 화폐 타입이 잘못되었습니다 => PlanetItemId:{data.PlanetItemId}");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void checkValidCaliverseItem(PlanetItemExchangePolicyMetaData data)
|
|
{
|
|
var caliverse_item_type = toEnum(data.CaliverseItemType, CaliverseItemType.None);
|
|
switch (caliverse_item_type)
|
|
{
|
|
case CaliverseItemType.Currency:
|
|
{
|
|
var currency_type = toEnum(data.CaliverseItemId, CurrencyType.None);
|
|
if (currency_type == CurrencyType.None)
|
|
{
|
|
addError(nameof(data.CaliverseItemId),
|
|
$"Caliverse 화폐 타입이 잘못되었습니다 => CaliverseItemId:{data.CaliverseItemId}");
|
|
}
|
|
|
|
// if (data.CaliverseItemAmount >= 0)
|
|
// {
|
|
// // 재화는 차감만 가능
|
|
// addError(nameof(data.CaliverseItemAmount),
|
|
// $"Caliverse 화폐 수량은 음수여야 합니다 => CaliverseItemAmount:{data.CaliverseItemAmount}");
|
|
// }
|
|
|
|
break;
|
|
}
|
|
case CaliverseItemType.CaliverseProduct:
|
|
{
|
|
var product_id = Convert.ToInt32(data.CaliverseItemId);
|
|
if (metaTable.ProductMetaTable.ProductMetaDataListbyId.ContainsKey(product_id) == false)
|
|
{
|
|
addError(nameof(data.CaliverseItemId),
|
|
$"CaliverseItemId이 존재하지 않습니다 => CaliverseItemId: {data.CaliverseItemId}");
|
|
}
|
|
|
|
if (data.CaliverseItemAmount < 0)
|
|
{
|
|
addError(nameof(data.CaliverseItemAmount),
|
|
$"Product 수량은 0보다 커야합니다 => CaliverseItemAmount:{data.CaliverseItemAmount}");
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CaliverseItemType.None:
|
|
default:
|
|
{
|
|
addError(nameof(data.CaliverseItemType),
|
|
$"Caliverse 아이템 타입이 잘못되었습니다 => CaliverseItemType:{data.CaliverseItemType}");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void addError(string variableName, string msg)
|
|
{
|
|
errors.add($"Invalid PlanetItemExchangePolicyMetaData Value: {variableName} - {msg}");
|
|
}
|
|
|
|
TEnum toEnum<TEnum>(string enumTypeString, TEnum defaultValue) where TEnum : struct, Enum
|
|
{
|
|
var enum_type_string_result = enumTypeString.Replace("_", "");
|
|
return Enum.TryParse<TEnum>(enum_type_string_result, ignoreCase: true, out var enum_type)
|
|
? enum_type
|
|
: defaultValue;
|
|
}
|
|
}
|
|
|
|
// 리소스 해제를 위한 Dispose 패턴 구현
|
|
private bool m_disposed = false;
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!m_disposed)
|
|
{
|
|
m_lock.Dispose();
|
|
m_disposed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 최신 메타테이블을 참조하는 클래스
|
|
public class BrokerMetaTableRef
|
|
{
|
|
public BrokerMetaTable MetaTable => m_meta_table;
|
|
private readonly BrokerMetaTable m_meta_table;
|
|
|
|
public BrokerMetaTableRef(BrokerMetaTable metaTable)
|
|
{
|
|
m_meta_table = metaTable;
|
|
}
|
|
}
|