초기커밋
This commit is contained in:
40
ServerCommon/Helper/BeaconHelper.cs
Normal file
40
ServerCommon/Helper/BeaconHelper.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Amazon.S3.Model;
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class BeaconHelper
|
||||
{
|
||||
public static async Task<(Result, string)> getBeaconAppProfileUploadPresignedUrl( this S3ConnectorBase s3connector
|
||||
, string bucketName
|
||||
, string beaconAppProfileS3Key )
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
(var is_success, var presigned_url) = await s3connector.getPresignedUrl( bucketName
|
||||
, beaconAppProfileS3Key
|
||||
, Amazon.S3.HttpVerb.PUT
|
||||
, DateTime.UtcNow.AddHours(1) );
|
||||
if ( false == is_success
|
||||
|| presigned_url.isNullOrWhiteSpace() )
|
||||
{
|
||||
err_msg = $"Failed to getPresignedUrl() !!!";
|
||||
result.setFail(ServerErrorCode.S3FileGetFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, presigned_url);
|
||||
}
|
||||
|
||||
return (result, presigned_url);
|
||||
}
|
||||
}
|
||||
65
ServerCommon/Helper/BusinessLogHelper.cs
Normal file
65
ServerCommon/Helper/BusinessLogHelper.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using ServerBase;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
//===================================================================================
|
||||
// LogAction + LogActionType 함께 생성해주는 클래스 이다.
|
||||
//===================================================================================
|
||||
|
||||
public partial class LogActionEx : LogAction
|
||||
{
|
||||
public LogActionEx(LogActionType logActionType)
|
||||
:base(logActionType.ToString())
|
||||
{
|
||||
}
|
||||
|
||||
public LogActionEx(LogActionType logActionType, Guid tranId)
|
||||
: base(logActionType.ToString(), tranId)
|
||||
{
|
||||
}
|
||||
|
||||
}//LogAction
|
||||
|
||||
//===================================================================================
|
||||
// ILogInvoker + LogDomainType 함께 생성해주는 클래스 이다.
|
||||
//===================================================================================
|
||||
|
||||
public abstract partial class ILogInvokerEx : ILogInvoker
|
||||
{
|
||||
public ILogInvokerEx(LogDomainType logDomainType)
|
||||
: base(logDomainType.ToString())
|
||||
{
|
||||
}
|
||||
|
||||
public ILogInvokerEx(LogDomainType logDomainType, LogAction logAction)
|
||||
: base(logDomainType.ToString(), logAction)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================================
|
||||
// QueryBatch + LogActionType 함께 생성해주는 클래스 이다.
|
||||
//==============================================================================================
|
||||
public class QueryBatchEx<TQueryRunner> : QueryBatch<TQueryRunner>
|
||||
where TQueryRunner : IQueryRunner, new()
|
||||
{
|
||||
public QueryBatchEx( IWithLogActor logActor
|
||||
, LogActionType logActionType
|
||||
, DynamoDbClient dbClient
|
||||
, bool isUseTransact = true, string transId = ""
|
||||
, UInt16 retryCount = 3, UInt16 retryDelayMSec = 1000, string eventTid = "" )
|
||||
: base( logActor, logActionType.ToString(), dbClient
|
||||
, isUseTransact, transId, retryCount, retryDelayMSec )
|
||||
{
|
||||
getQueryRunner().setQueryBatch(this);
|
||||
}
|
||||
}
|
||||
61
ServerCommon/Helper/ClientMessageHelper.cs
Normal file
61
ServerCommon/Helper/ClientMessageHelper.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class ClientMessageHelper
|
||||
{
|
||||
public static global::Item toItemData4Client(this ItemBase item)
|
||||
{
|
||||
var parent = item.getRootParent();
|
||||
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
||||
|
||||
var item_attribute = item.getEntityAttribute<ItemAttributeBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {parent.toBasicString()}");
|
||||
|
||||
return item_attribute.toItemData4Client();
|
||||
}
|
||||
|
||||
public static global::Item toItemData4Client(this ItemAttributeBase itemAttributeBase)
|
||||
{
|
||||
var owner = itemAttributeBase.getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
var parent = owner.getRootParent();
|
||||
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var item_4_client = new global::Item();
|
||||
|
||||
item_4_client.ItemGuid = itemAttributeBase.ItemGuid;
|
||||
item_4_client.ItemId = (Int32)itemAttributeBase.ItemMetaId;
|
||||
item_4_client.Count = itemAttributeBase.ItemStackCount;
|
||||
item_4_client.Slot = itemAttributeBase.EquipedPos;
|
||||
item_4_client.Level = itemAttributeBase.Level;
|
||||
item_4_client.Attributeids.AddRange(itemAttributeBase.Attributes.Select<UInt16, Int32>(x => x).ToList());
|
||||
|
||||
(var result, DynamoDbDocBase? doc_base) = itemAttributeBase.toDocBase(false).GetAwaiter().GetResult();
|
||||
if(result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to toDocBase() !!!, in toItemData4Client() : {result.toBasicString()} - {owner.toBasicString()}, {parent.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return item_4_client;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(doc_base, () => $"doc_base is null !!! - {itemAttributeBase.toBasicString()}");
|
||||
|
||||
item_4_client.CreateTime = doc_base.getCreatedDateTime().ProcessedTime.ToTimestamp();
|
||||
item_4_client.CreateTime = doc_base.getUpdatedDateTime().ProcessedTime.ToTimestamp();
|
||||
|
||||
return item_4_client;
|
||||
}
|
||||
}
|
||||
168
ServerCommon/Helper/CommonResultHelper.cs
Normal file
168
ServerCommon/Helper/CommonResultHelper.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class CommonResultHelper
|
||||
{
|
||||
public static string toBasicString(this global::Item item)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
data += $"itemGuid:{item.ItemGuid}, itemMetaId:{item.ItemId}, stackCount:{item.Count}";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::LevelExp levelExp)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
data += $"Level:{levelExp.Level}, ExpInLevel:{levelExp.ExpInLevel}, ExpInTotal:{levelExp.ExpInTotal}";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::EntityCommonResult entityCommonResult)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
data = $"{entityCommonResult.Money.toBasicString()}"
|
||||
+ $"{entityCommonResult.Item.toBasicString()}"
|
||||
+ $"{entityCommonResult.Exp.toBasicString()}";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::MoneyDeltaAmount moneyDelta)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
data += $"deltaType:{moneyDelta.DeltaType}, amount:{moneyDelta.Amount}";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::MoneyResult moneyResult)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
foreach (var each in moneyResult.Moneys)
|
||||
{
|
||||
var currency_type = (CurrencyType)each.Key;
|
||||
var count = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $"money: currencyType:{currency_type}, count:{count}";
|
||||
}
|
||||
foreach (var each in moneyResult.Deltas)
|
||||
{
|
||||
var currency_type = (CurrencyType)each.Key;
|
||||
var money_delta = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $"money.delta: currencyType:{currency_type}, {money_delta.toBasicString()}";
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::ItemAmount itemAmount)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
data += $"itemMetaId:{itemAmount.MetaId}, itemCount:{itemAmount.Amount}";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::ItemDeltaAmount itemDelta)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
data += $"deltaType:{itemDelta.DeltaType}, {itemDelta.Delta.toBasicString()}";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::ItemResult itemResult)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
foreach (var each in itemResult.UpdatedItems)
|
||||
{
|
||||
var item_guid = each.Key;
|
||||
var item = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $"item.Updated: {item.toBasicString()}";
|
||||
}
|
||||
foreach (var each in itemResult.NewItems)
|
||||
{
|
||||
var item_guid = each.Key;
|
||||
var item_delta = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $"item.New: {item_delta.toBasicString()}";
|
||||
}
|
||||
foreach (var each in itemResult.DeltaPerMeta)
|
||||
{
|
||||
var item_meta_id = each.Key;
|
||||
var item_delta = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $"item.DeltaPerMeta: {item_delta.toBasicString()}";
|
||||
}
|
||||
foreach (var each in itemResult.DeltaPerItems)
|
||||
{
|
||||
var item_guid = each.Key;
|
||||
var deleta_count = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $"item.DeltaPerGuid: itemGuid:{item_guid}, deltaCount:{deleta_count}";
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::LevelExpDeltaAmount levelExpDelta)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
data += $"expDeltaType:{levelExpDelta.ExpDeltaType}, expDeltaAmount:{levelExpDelta.ExpAmount}, levelDeltaAmount:{levelExpDelta.LevelAmount}";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string toBasicString(this global::ExpResult expResult)
|
||||
{
|
||||
var data = string.Empty;
|
||||
|
||||
foreach (var each in expResult.LevelExps)
|
||||
{
|
||||
var level_exp_type = (LevelExpType)each.Key;
|
||||
var level_exp = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $"exp: {level_exp.toBasicString()}";
|
||||
}
|
||||
foreach (var each in expResult.LevelExpDeltas)
|
||||
{
|
||||
var level_exp_type = (LevelExpType)each.Key;
|
||||
var level_exp_delta = each.Value;
|
||||
|
||||
data += $"\n";
|
||||
data += $":exp.Delta: {level_exp_delta.toBasicString()}";
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
43
ServerCommon/Helper/ConfigHelper.cs
Normal file
43
ServerCommon/Helper/ConfigHelper.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
|
||||
|
||||
using ServerCore;
|
||||
|
||||
|
||||
|
||||
using WORLD_META_ID = System.UInt32;
|
||||
using CHANNEL_NO = System.UInt32;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class ConfigHelper
|
||||
{
|
||||
public static WORLD_META_ID getWorldId(this IConfiguration config)
|
||||
{
|
||||
return uint.Parse(config["worldId"] ?? "0");
|
||||
}
|
||||
|
||||
public static ushort getPort(this IConfiguration config)
|
||||
{
|
||||
return ushort.Parse(config["port"] ?? "0");
|
||||
}
|
||||
|
||||
public static CHANNEL_NO getChannelNo(this IConfiguration config)
|
||||
{
|
||||
return uint.Parse(config["channelNo"] ?? "0");
|
||||
}
|
||||
|
||||
public static ServerType getServerType(this IConfiguration config)
|
||||
{
|
||||
var value = config["config"];
|
||||
|
||||
if (Enum.TryParse<ServerType>(value, true, out var serverType))
|
||||
{
|
||||
return serverType;
|
||||
}
|
||||
|
||||
throw new Exception($"Invalid or missing ServerType in IConfiguration:{value}");
|
||||
}
|
||||
}
|
||||
245
ServerCommon/Helper/CurrencyControlHelper.cs
Normal file
245
ServerCommon/Helper/CurrencyControlHelper.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using Amazon.DynamoDBv2;
|
||||
using Amazon.DynamoDBv2.DocumentModel;
|
||||
using Amazon.DynamoDBv2.Model;
|
||||
using Amazon.S3.Model;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
using DYNAMO_DB_TABLE_NAME = System.String;
|
||||
using DYNAMO_DB_TABLE_FULL_NAME = System.String;
|
||||
using USER_GUID = System.String;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class CurrencyControlHelper
|
||||
{
|
||||
private static DynamoDbClient? m_db_connector = null;
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
// 단위당 금전량을 quantity 만큼 계산하여 Round 보정후 반환 한다.
|
||||
//=============================================================================================
|
||||
public static double calculateRoundedMoneyByCurrency(this double reqUnitMoney, CurrencyType currencyType, int quantity = 1)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
if (ServerCore.TypeHelper.NumericSignType.Positive == ServerCore.TypeHelper.checkNumericSignType<double>(reqUnitMoney))
|
||||
{
|
||||
reqUnitMoney *= -1;
|
||||
}
|
||||
|
||||
var req_money = reqUnitMoney * quantity;
|
||||
|
||||
return roundMoneyByCurrencyType(currencyType, req_money);
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// 금전량을 보정 한다.
|
||||
//=============================================================================================
|
||||
public static double roundMoneyByCurrencyType(CurrencyType currencyType, double delta)
|
||||
{
|
||||
// CurrencyType.Calium 이 아닌 모든 재화는 소숫점을 올림 처리 한다 !!!
|
||||
if (currencyType != CurrencyType.Calium)
|
||||
{
|
||||
delta = MathHelper.roundUpOrDown(delta);
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// delta 만큼 금전을 쓴다.
|
||||
//=============================================================================================
|
||||
public static async Task<(Result, double)> spendMoneyByUserGuid( USER_GUID userGuid, CurrencyType currencyType, double delta )
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
if (ServerCore.TypeHelper.NumericSignType.Positive == ServerCore.TypeHelper.checkNumericSignType<double>(delta))
|
||||
{
|
||||
delta *= -1;
|
||||
}
|
||||
|
||||
return await changeMoneyByUserGuid(userGuid, currencyType, delta);
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// delta 만큼 금전을 얻는다.
|
||||
//=============================================================================================
|
||||
public static async Task<(Result, double)> earnMoneyByUserGuid(USER_GUID userGuid, CurrencyType currencyType, double delta)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
if (ServerCore.TypeHelper.NumericSignType.Negative == ServerCore.TypeHelper.checkNumericSignType<double>(delta))
|
||||
{
|
||||
delta *= -1;
|
||||
}
|
||||
|
||||
if (0 < delta)
|
||||
{
|
||||
return await changeMoneyByUserGuid(userGuid, currencyType, delta);
|
||||
}
|
||||
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
public static async Task<(Result, double)> getMoneyByUserGuid(USER_GUID userGuid, CurrencyType type)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
var error_code = hasDbConnector();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Not available DynamoDB connector !!! : userGuid:{userGuid}";
|
||||
result.setFail(error_code, err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
var db_connector = getDbConnector();
|
||||
|
||||
(result, var found_money_doc) = await findMoneyDocByUserGuid(db_connector, userGuid);
|
||||
if (null == found_money_doc)
|
||||
{
|
||||
err_msg = $"Not found MoneyDoc !!! : userGuid:{userGuid}";
|
||||
result.setFail(ServerErrorCode.MoneyDocIsNull, err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
var attrib = found_money_doc.getAttrib<MoneyAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(attrib, () => $"attrib is null !!!");
|
||||
|
||||
return (result, attrib.getCurrencyFromType(type));
|
||||
}
|
||||
|
||||
public static async Task<(Result, double)> changeMoneyByUserGuid(USER_GUID userGuid, CurrencyType type, double delta)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var error_code = hasDbConnector();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Not available DynamoDB connector !!! : userGuid:{userGuid}";
|
||||
result.setFail(error_code, err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
var db_connector = getDbConnector();
|
||||
|
||||
var table = db_connector.getTableByDoc<MoneyDoc>();
|
||||
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<MoneyDoc>(userGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, 0);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - userGuid:{userGuid}");
|
||||
|
||||
(result, var request) = makeUpdateItemRequest( table.TableName
|
||||
, make_primary_key.toKeyWithAttributeValue(), MoneyAttribExtensions.getKeyNameFromType(type)
|
||||
, delta);
|
||||
if (result.isFail() || request == null) return (result, 0);
|
||||
|
||||
(result, var changed_money_doc) = await db_connector.simpleQueryDocTypesWithUpdateItemRequest<MoneyDoc>(request);
|
||||
if (result.isFail() || changed_money_doc == null) return (result, 0);
|
||||
|
||||
var money_attrib = changed_money_doc.getAttrib<MoneyAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(money_attrib, () => $"money_attrib is null !!! - userGuid:{userGuid}");
|
||||
|
||||
return (result, money_attrib.getCurrencyFromType(type));
|
||||
}
|
||||
|
||||
public static async Task<(Result, MoneyDoc?)> findMoneyDocByUserGuid(DynamoDbClient dynamoDbClient, USER_GUID userGuid)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var money_doc = new MoneyDoc();
|
||||
money_doc.setCombinationKeyForPK(userGuid);
|
||||
money_doc.onApplyPKSK();
|
||||
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKOnly(money_doc.getPK());
|
||||
|
||||
return await dynamoDbClient.simpleQueryDocTypeWithQueryOperationConfig<MoneyDoc>(query_config);
|
||||
}
|
||||
|
||||
private static (Result, UpdateItemRequest?) makeUpdateItemRequest( DYNAMO_DB_TABLE_FULL_NAME tableFullName
|
||||
, Dictionary<string, AttributeValue> attributeValueWithPrimaryKey
|
||||
, string targetAttribName
|
||||
, double deltaCount )
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var error_code = hasDbConnector();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Not available DynamoDb connector !!!";
|
||||
result.setFail(error_code, err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var query_builder = new DynamoDbItemRequestHelper.UpdateItemRequestBuilder(tableFullName);
|
||||
query_builder.withKeys(attributeValueWithPrimaryKey);
|
||||
|
||||
var target_doc = new MoneyDoc();
|
||||
var attrib_path_json_string = target_doc.toJsonStringOfAttribs();
|
||||
var target_key = JsonHelper.getJsonPropertyName<MoneyAttrib>(targetAttribName);
|
||||
(var is_success, var attribute_expression) = DynamoDbClientHelper.toAttributeExpressionFromJson(attrib_path_json_string, target_key);
|
||||
if (false == is_success)
|
||||
{
|
||||
err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : attribPath:{attrib_path_json_string}, targetKey:{target_key}";
|
||||
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
query_builder.withExpressionAttributeNames(DynamoDbClientHelper.toExpressionAttributeNamesFromJson(attrib_path_json_string, target_key));
|
||||
|
||||
var update_expression = (deltaCount >= 0)
|
||||
? $"SET {attribute_expression} = if_not_exists({attribute_expression}, :start) + :changeValue"
|
||||
: $"SET {attribute_expression} = if_not_exists({attribute_expression}, :start) - :changeValue";
|
||||
query_builder.withUpdateExpression(update_expression);
|
||||
|
||||
var expression_attribute_values = new Dictionary<string, AttributeValue>
|
||||
{
|
||||
{ ":changeValue", new AttributeValue { N = Math.Abs(deltaCount).ToString() } },
|
||||
{ ":start", new AttributeValue { N = "0" } }
|
||||
};
|
||||
query_builder.withExpressionAttributeValues(expression_attribute_values);
|
||||
|
||||
query_builder.withReturnValues(ReturnValue.ALL_NEW);
|
||||
|
||||
return query_builder.build();
|
||||
}
|
||||
|
||||
private static ServerErrorCode hasDbConnector()
|
||||
{
|
||||
if(null == m_db_connector)
|
||||
{
|
||||
return ServerErrorCode.DynamoDbConnectorIsNull;
|
||||
}
|
||||
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
public static DynamoDbClient getDbConnector()
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(m_db_connector, () => $"m_db_connector is null !!!");
|
||||
return m_db_connector;
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// CurrencyControlHelper <= DynamoDbClient 설정
|
||||
//=============================================================================================
|
||||
public static Result setDbConnector(DynamoDbClient dbConnector)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
m_db_connector = dbConnector;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
82
ServerCommon/Helper/DataCopyHelper.cs
Normal file
82
ServerCommon/Helper/DataCopyHelper.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class DataCopyHelper
|
||||
{
|
||||
#region 데이터 복사 하기 : Meta => Doc
|
||||
public static async Task<Result> copyDocFromMetas<TDoc>(TDoc toDoc, List<MetaAssets.IMetaData> fromMetaDatas)
|
||||
where TDoc : DynamoDbDocBase
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var to_doc = toDoc as ICopyDocFromMeta;
|
||||
if (null == to_doc)
|
||||
{
|
||||
err_msg = $"Failed to cast ICopyDocFromMeta !!! : {typeof(TDoc).Name}";
|
||||
result.setFail(ServerErrorCode.ClassDoesNotImplementInterfaceInheritance, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var meta_data in fromMetaDatas)
|
||||
{
|
||||
if (false == to_doc.copyDocFromMeta(meta_data))
|
||||
{
|
||||
err_msg = $"Failed to copyDocFromMeta() !!!, to:{typeof(TDoc).Name}, from:{meta_data.getTypeName()}";
|
||||
result.setFail(ServerErrorCode.MetaDataCopyToDynamoDbDocFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 데이터 복사 하기 : Meta => EntityAttribute
|
||||
public static async Task<Result> copyEntityAttributeFromMetas<TEntityAttributeType>(TEntityAttributeType toDocBase, List<MetaAssets.IMetaData> metaDatas)
|
||||
where TEntityAttributeType : EntityAttributeBase
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var to_copy = toDocBase as ICopyEntityAttributeFromMeta;
|
||||
if (null == to_copy)
|
||||
{
|
||||
err_msg = $"Failed to cast ICopyEntityAttributeFromMeta !!! : {typeof(TEntityAttributeType).Name} !!!";
|
||||
result.setFail(ServerErrorCode.ClassDoesNotImplementInterfaceInheritance, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var meta_data in metaDatas)
|
||||
{
|
||||
if (false == to_copy.copyEntityAttributeFromMeta(meta_data))
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromMeta() !!!, to:{typeof(TEntityAttributeType).Name}, from:{meta_data.getTypeName()}";
|
||||
result.setFail(ServerErrorCode.MetaDataCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
42
ServerCommon/Helper/EffectHelper.cs
Normal file
42
ServerCommon/Helper/EffectHelper.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class EffectHelper
|
||||
{
|
||||
public static FarmingStateType toFarmingStateType( this PropState propState )
|
||||
{
|
||||
switch(propState)
|
||||
{
|
||||
case PropState.Activation:
|
||||
return FarmingStateType.StandBy;
|
||||
case PropState.Progress:
|
||||
return FarmingStateType.Progress;
|
||||
case PropState.Respawning:
|
||||
return FarmingStateType.CoolingTime;
|
||||
}
|
||||
|
||||
return FarmingStateType.None;
|
||||
}
|
||||
|
||||
public static PropState toPropState(this FarmingStateType farmingStateType)
|
||||
{
|
||||
switch (farmingStateType)
|
||||
{
|
||||
case FarmingStateType.StandBy:
|
||||
return PropState.Activation;
|
||||
case FarmingStateType.Progress:
|
||||
return PropState.Progress;
|
||||
case FarmingStateType.CoolingTime:
|
||||
return PropState.Respawning;
|
||||
}
|
||||
|
||||
return PropState.None;
|
||||
}
|
||||
}
|
||||
169
ServerCommon/Helper/EntityHelper.cs
Normal file
169
ServerCommon/Helper/EntityHelper.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerControlCenter;
|
||||
|
||||
|
||||
using USER_GUID = System.String;
|
||||
using MASTER_GUID = System.String;
|
||||
using MASTER_NICKNAME = System.String;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Amazon.S3.Model;
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class EntityHelper
|
||||
{
|
||||
public class MasterProfile
|
||||
{
|
||||
public MASTER_GUID MasterGuid { get; set; } = string.Empty;
|
||||
public MASTER_NICKNAME MasterNickname { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public static (Result, MasterProfile?) getMasterProfile<TMasterEntity>(EntityBase owner)
|
||||
where TMasterEntity : EntityBase
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var master_entity = owner as TMasterEntity;
|
||||
if (null == master_entity)
|
||||
{
|
||||
if (true == owner.hasMasterGuid())
|
||||
{
|
||||
master_entity = owner.onGetMasterEntity() as TMasterEntity;
|
||||
if (null == master_entity)
|
||||
{
|
||||
err_msg = $"Not related Master !!! : TMasterEntity:{nameof(TMasterEntity)} - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err_msg = $"Not related Master !!! : TMasterEntity:{nameof(TMasterEntity)} - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MasterNotRelated, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
var entity_profile = new MasterProfile();
|
||||
entity_profile.MasterGuid = (master_entity as dynamic).getUserGuid(); // 나중에 가상함수로 수정 하자. - kangms
|
||||
entity_profile.MasterNickname = (master_entity as dynamic).getUserNickname(); // 나중에 가상함수로 수정 하자. - kangms
|
||||
|
||||
return (result, entity_profile);
|
||||
}
|
||||
|
||||
public static OwnerEntityType toOwnerEntityType(this EntityType entityType)
|
||||
{
|
||||
if (EntityType.Player == entityType)
|
||||
{
|
||||
return OwnerEntityType.User;
|
||||
}
|
||||
else if (EntityType.Character == entityType)
|
||||
{
|
||||
return OwnerEntityType.Character;
|
||||
}
|
||||
else if (EntityType.UgcNpc == entityType
|
||||
|| EntityType.Beacon == entityType)
|
||||
{
|
||||
return OwnerEntityType.UgcNpc;
|
||||
}
|
||||
else if (EntityType.MyHome == entityType)
|
||||
{
|
||||
return OwnerEntityType.Myhome;
|
||||
}
|
||||
|
||||
var err_msg = $"Invalid EntityType !!! : EntityType:{entityType}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return OwnerEntityType.None;
|
||||
}
|
||||
|
||||
public static async Task<(Result, bool)> isUserLoggedIn(DynamoDbClient dynamoDbClient, USER_GUID userGuid)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
// 1. UserBaseDoc 조회
|
||||
(result, var user_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UserBaseDoc>(userGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, false);
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(user_primary_key, $"user_primary_key is null !!! - userGuid:{userGuid}");
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKSK(user_primary_key.PK);
|
||||
|
||||
(result, var user_base_doc) = await dynamoDbClient.simpleQueryDocTypeWithQueryOperationConfig<UserBaseDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, false);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(user_base_doc, () => $"user_base_doc is null !!! : userGuid:{userGuid}");
|
||||
|
||||
// 2. LoggedIn 체크
|
||||
var user_base_attrib = user_base_doc.getAttrib<UserBaseAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_base_attrib, () => $"user_base_attrib is null !!!");
|
||||
|
||||
return (result, (user_base_attrib.GameLoginDateTime > user_base_attrib.GameLogoutDateTime));
|
||||
}
|
||||
|
||||
public static async Task<(Result, List<ItemDoc>?)> findUserItemsWithCondition( DynamoDbClient dynamoDbClient, USER_GUID userGuid
|
||||
, Func<ItemDoc, bool>? filterCondition )
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
// 1. ItemDoc 조회
|
||||
(result, var user_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<ItemDoc>(userGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(user_primary_key, $"user_primary_key is null !!! - userGuid:{userGuid}");
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKOnly(user_primary_key.PK);
|
||||
|
||||
(result, var found_item_docs) = await dynamoDbClient.simpleQueryDocTypesWithQueryOperationConfig<ItemDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_item_docs, () => $"found_item_docs is null !!! : userGuid:{userGuid}");
|
||||
|
||||
if (null != filterCondition)
|
||||
{
|
||||
// 2. ItemDoc 조건 체크 !!!
|
||||
var filtered_item_docs = new List<ItemDoc>();
|
||||
|
||||
foreach(var item_doc in found_item_docs)
|
||||
{
|
||||
var is_success = filterCondition.Invoke(item_doc);
|
||||
if (is_success.isFalse())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
filtered_item_docs.Add(item_doc);
|
||||
}
|
||||
|
||||
return (result, filtered_item_docs);
|
||||
}
|
||||
|
||||
return (result, found_item_docs);
|
||||
}
|
||||
}
|
||||
297
ServerCommon/Helper/EntitySearchHelper.cs
Normal file
297
ServerCommon/Helper/EntitySearchHelper.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
|
||||
using SESSION_ID = System.Int32;
|
||||
using META_ID = System.UInt32;
|
||||
using ENTITY_GUID = System.String;
|
||||
using ACCOUNT_ID = System.String;
|
||||
using OWNER_GUID = System.String;
|
||||
using USER_GUID = System.String;
|
||||
using CHARACTER_GUID = System.String;
|
||||
using ITEM_GUID = System.String;
|
||||
using NICKNAME = System.String;
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public class UserByAccountIdResult
|
||||
{
|
||||
public string UserGuid { get; set; } = null!;
|
||||
public string Nickname { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class UserInfoByUserNickname
|
||||
{
|
||||
public USER_GUID UserGuid { get; set; } = string.Empty;
|
||||
public NICKNAME UserNickname { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class UgcNpcInfoByUgcNpcNickname
|
||||
{
|
||||
public UgcNpcAttrib UgcNpcAttrib { get; set; } = null!;
|
||||
}
|
||||
|
||||
public static class EntitySearchHelper
|
||||
{
|
||||
public static async Task<(Result, UserByAccountIdResult?)> findUserByAccountId(DynamoDbClient dynamoDbClient, ACCOUNT_ID accountId, string tryUserEmailId)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if(true == accountId.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Invalid AccountId !!! - tryUserEmailId:{tryUserEmailId}";
|
||||
result.setFail(ServerErrorCode.AccountIdInvalid, err_msg);
|
||||
Log.getLogger(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
(result, var found_account_doc) = await AccountBaseDoc.findUserGuidFromAccountId(dynamoDbClient, accountId);
|
||||
if(result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_account_doc, () => $"found_account_doc is null !!! - AccountId:{accountId}, tryUserEmailId:{tryUserEmailId}");
|
||||
|
||||
var doc_account_base_attrib = found_account_doc.getAttrib<AccountBaseAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(doc_account_base_attrib, () => $"doc_account_base_attrib is null !!! - AccountId:{accountId}, tryUserEmailId:{tryUserEmailId}");
|
||||
|
||||
var user_guid = doc_account_base_attrib.UserGuid;
|
||||
if (true == user_guid.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Account without UserGuid !!! - AccountId:{accountId}, tryUserEmailId:{tryUserEmailId}";
|
||||
result.setFail(ServerErrorCode.AccountWithoutUserGuid, err_msg);
|
||||
Log.getLogger(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
string found_nickname = string.Empty;
|
||||
(result, var found_nickname_attrib) = await NicknameDoc.findNicknameFromGuid(dynamoDbClient, user_guid);
|
||||
if(result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_nickname_attrib, () => $"found_nickname_attrib is null !!!, userGuid:{user_guid} - AccountId:{accountId}, tryUserEmailId:{tryUserEmailId}");
|
||||
found_nickname = found_nickname_attrib.Nickname;
|
||||
|
||||
return (result, new UserByAccountIdResult
|
||||
{
|
||||
UserGuid = user_guid,
|
||||
Nickname = found_nickname,
|
||||
});
|
||||
}
|
||||
|
||||
public static async Task<(Result, List<UgcNpcAttrib>?)> findUgcNpcAttribAllByUserGuid(DynamoDbClient dynamoDbClient, USER_GUID userGuid, string tryUserEmailId)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (true == userGuid.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Invalid UserGuid !!! - tryUserEmailId:{tryUserEmailId}";
|
||||
result.setFail(ServerErrorCode.UserGuidInvalid, err_msg);
|
||||
Log.getLogger(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UgcNpcDoc>(userGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - UserGuid:{userGuid}, tryUserEmailId:{tryUserEmailId}");
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKOnly(make_primary_key.PK);
|
||||
|
||||
(result, var found_ugc_npc_docs) = await dynamoDbClient.simpleQueryDocTypesWithQueryOperationConfig<UgcNpcDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var found_ugc_npc_attribs = new List<UgcNpcAttrib>();
|
||||
|
||||
foreach(var doc in found_ugc_npc_docs)
|
||||
{
|
||||
var ugc_npc_attrib = doc.getAttrib<UgcNpcAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_attrib, () => $"ugc_npc_attrib is null !!! - UserGuid:{userGuid}, tryUserEmailId:{tryUserEmailId}");
|
||||
|
||||
found_ugc_npc_attribs.Add(ugc_npc_attrib);
|
||||
}
|
||||
|
||||
return (result, found_ugc_npc_attribs);
|
||||
}
|
||||
|
||||
public static async Task<(Result, UserInfoByUserNickname?)> findUserInfoByUserNickname(DynamoDbClient dynamoDbClient, NICKNAME userNickname)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (true == userNickname.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Empty UserNickname !!!";
|
||||
result.setFail(ServerErrorCode.UserNicknameEmpty, err_msg);
|
||||
Log.getLogger(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UserNicknameRegistryDoc>(DynamoDbClient.PK_GLOBAL, userNickname);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - userNickname:{userNickname}");
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKSK(make_primary_key.PK, make_primary_key.SK);
|
||||
|
||||
(result, var found_user_nickname_doc) = await dynamoDbClient.simpleQueryDocTypeWithQueryOperationConfig<UserNicknameRegistryDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_user_nickname_doc, () => $"found_user_nickname_doc is null !!! - userNickname:{userNickname}");
|
||||
|
||||
var user_nickname_registry_attrib = found_user_nickname_doc.getAttrib<UserNicknameRegistryAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_nickname_registry_attrib, () => $"user_nickname_registry_attrib is null !!! - userNickname:{userNickname}");
|
||||
|
||||
var searched_result = new UserInfoByUserNickname();
|
||||
|
||||
searched_result.UserNickname = user_nickname_registry_attrib.Nickname;
|
||||
searched_result.UserGuid = user_nickname_registry_attrib.UserGuid;
|
||||
|
||||
return (result, searched_result);
|
||||
}
|
||||
|
||||
public static async Task<(Result, UgcNpcInfoByUgcNpcNickname?)> findUgcNpcInfoByUgcNpcNickname( DynamoDbClient dynamoDbClient
|
||||
, OwnerEntityType ownerEntityType, OWNER_GUID ownerGuid
|
||||
, NICKNAME ugcNpcNickname )
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (true == ugcNpcNickname.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Empty UgcNpcNickname !!!";
|
||||
result.setFail(ServerErrorCode.UgcNpcNicknameEmpty, err_msg);
|
||||
Log.getLogger(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
UgcNpcNicknameRegistryDoc? found_ugc_nickname_registry_doc = null;
|
||||
{
|
||||
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UgcNpcNicknameRegistryDoc>(ownerGuid, ugcNpcNickname);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - userGuid:{ownerGuid}, userNickname:{ugcNpcNickname}");
|
||||
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKSK(make_primary_key.PK, make_primary_key.SK);
|
||||
(result, found_ugc_nickname_registry_doc) = await dynamoDbClient.simpleQueryDocTypeWithQueryOperationConfig<UgcNpcNicknameRegistryDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_ugc_nickname_registry_doc, () => $"found_ugc_nickname_registry_doc is null !!! - userGuid:{ownerGuid}, userNickname:{ugcNpcNickname}");
|
||||
}
|
||||
var ugc_npc_nickname_registry_attrib = found_ugc_nickname_registry_doc.getAttrib<UgcNpcNicknameRegistryAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_nickname_registry_attrib, () => $"ugc_npc_nickname_registry_attrib is null !!! - userGuid:{ownerGuid}, userNickname:{ugcNpcNickname}");
|
||||
|
||||
UgcNpcDoc? found_ugc_npc_doc = null;
|
||||
{
|
||||
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UgcNpcDoc>(ownerGuid, ugc_npc_nickname_registry_attrib.UgcNpcMetaGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - userGuid:{ownerGuid}, userNickname:{ugcNpcNickname}");
|
||||
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKSK(make_primary_key.PK, make_primary_key.SK);
|
||||
(result, found_ugc_npc_doc) = await dynamoDbClient.simpleQueryDocTypeWithQueryOperationConfig<UgcNpcDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_ugc_npc_doc, () => $"found_ugc_npc_doc is null !!! - userGuid:{ownerGuid}, userNickname:{ugcNpcNickname}");
|
||||
}
|
||||
var ugc_npc_attrib = found_ugc_npc_doc.getAttrib<UgcNpcAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_attrib, () => $"ugc_npc_attrib is null !!! - userGuid:{ownerGuid}, userNickname:{ugcNpcNickname}");
|
||||
|
||||
var searched_result = new UgcNpcInfoByUgcNpcNickname();
|
||||
if(null != ugc_npc_attrib)
|
||||
{
|
||||
searched_result.UgcNpcAttrib = ugc_npc_attrib;
|
||||
}
|
||||
|
||||
return (result, searched_result);
|
||||
}
|
||||
|
||||
public static async Task<(Result, MoneyAttrib?)> findUserMoneyByUserGuid(DynamoDbClient dynamoDbClient, USER_GUID userGuid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (true == userGuid.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Invalid UserGuid !!!";
|
||||
result.setFail(ServerErrorCode.UserGuidInvalid, err_msg);
|
||||
Log.getLogger(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<MoneyDoc>(userGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - userGuid:{userGuid}");
|
||||
var query_config = dynamoDbClient.makeQueryConfigForReadByPKOnly(make_primary_key.PK);
|
||||
|
||||
(result, var found_money_doc) = await dynamoDbClient.simpleQueryDocTypeWithQueryOperationConfig<MoneyDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_money_doc, () => $"found_money_doc is null !!! - userGuid:{userGuid}");
|
||||
|
||||
var money_attrib = found_money_doc.getAttrib<MoneyAttrib>();
|
||||
if(money_attrib == null)
|
||||
{
|
||||
err_msg = $"money_attrib is null !!! - UserGuid:{userGuid} !!! {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UserMoneyDocEmpty, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, money_attrib);
|
||||
}
|
||||
}
|
||||
407
ServerCommon/Helper/InventoryRuleHelper.cs
Normal file
407
ServerCommon/Helper/InventoryRuleHelper.cs
Normal file
@@ -0,0 +1,407 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using MetaAssets;
|
||||
using ServerControlCenter;
|
||||
|
||||
|
||||
using SESSION_ID = System.Int32;
|
||||
using META_ID = System.UInt32;
|
||||
using ENTITY_GUID = System.String;
|
||||
using ACCOUNT_ID = System.String;
|
||||
using OWNER_GUID = System.String;
|
||||
using USER_GUID = System.String;
|
||||
using CHARACTER_GUID = System.String;
|
||||
using ITEM_GUID = System.String;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class InventoryRuleHelper
|
||||
{
|
||||
public static Int16 getBagTapMaxSlotCount()
|
||||
{
|
||||
return MetaHelper.GameConfigMeta.MaxItemCategorySlotNum;
|
||||
}
|
||||
|
||||
// 임시로 관련 메타 정보를 반환 한다.
|
||||
// 추후 인벤토리 메타 정보를 추가하여 처리되도록 개선하자. - kangms
|
||||
public static Int16 getBagTapMaxSlotCountByBagTabType(EntityType entityType, BagTabType tabType)
|
||||
{
|
||||
switch (entityType)
|
||||
{
|
||||
case EntityType.MyHome:
|
||||
return getMyHomeMaxSlotCountByBagTabType(tabType);
|
||||
|
||||
default:
|
||||
return getNormalMaxSlotCountByBagTabType(tabType);
|
||||
}
|
||||
}
|
||||
public static Int16 getNormalMaxSlotCountByBagTabType(BagTabType tabType)
|
||||
{
|
||||
switch (tabType)
|
||||
{
|
||||
case BagTabType._0:
|
||||
return MetaHelper.GameConfigMeta.Inventory1Slot;
|
||||
|
||||
case BagTabType._1:
|
||||
return MetaHelper.GameConfigMeta.Inventory3Slot;
|
||||
|
||||
case BagTabType._2:
|
||||
return MetaHelper.GameConfigMeta.Inventory5Slot;
|
||||
|
||||
case BagTabType._3:
|
||||
return MetaHelper.GameConfigMeta.Inventory7Slot;
|
||||
|
||||
case BagTabType._4:
|
||||
return MetaHelper.GameConfigMeta.Inventory9Slot;
|
||||
|
||||
case BagTabType._5:
|
||||
return MetaHelper.GameConfigMeta.Inventory2Slot;
|
||||
|
||||
case BagTabType._6:
|
||||
return MetaHelper.GameConfigMeta.Inventory4Slot;
|
||||
|
||||
case BagTabType._7:
|
||||
return MetaHelper.GameConfigMeta.Inventory6Slot;
|
||||
|
||||
case BagTabType._8:
|
||||
return MetaHelper.GameConfigMeta.Inventory8Slot;
|
||||
|
||||
case BagTabType._9:
|
||||
return MetaHelper.GameConfigMeta.Inventory10Slot;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid BagTabType !!!, in getNormalMaxSlotCountByBagTabType() : BagTabType:{tabType}");
|
||||
}
|
||||
}
|
||||
|
||||
public static Int16 getMyHomeMaxSlotCountByBagTabType(BagTabType tabType)
|
||||
{
|
||||
switch (tabType)
|
||||
{
|
||||
case BagTabType._0:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory1Slot;
|
||||
|
||||
case BagTabType._1:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory3Slot;
|
||||
|
||||
case BagTabType._2:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory5Slot;
|
||||
|
||||
case BagTabType._3:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory7Slot;
|
||||
|
||||
case BagTabType._4:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory9Slot;
|
||||
|
||||
case BagTabType._5:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory2Slot;
|
||||
|
||||
case BagTabType._6:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory4Slot;
|
||||
|
||||
case BagTabType._7:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory6Slot;
|
||||
|
||||
case BagTabType._8:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory8Slot;
|
||||
|
||||
case BagTabType._9:
|
||||
return MetaHelper.GameConfigMeta.MyHomeInventory10Slot;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid BagTabType !!!, in getMyHomeMaxSlotCountByBagTabType() : BagTabType:{tabType}");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ITEM_GUID> findContainDuplicatedItemGuid(List<ITEM_GUID> toCheckItemGuids)
|
||||
{
|
||||
return toCheckItemGuids.GroupBy(x => x)
|
||||
.Where(g => g.Count() > 1)
|
||||
.Select(g => g.Key)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static InvenEquipType toInvenEquipType(this EntityType entityInvenType)
|
||||
{
|
||||
switch (entityInvenType)
|
||||
{
|
||||
case EntityType.ClothEquipInven:
|
||||
return InvenEquipType.Cloth;
|
||||
|
||||
case EntityType.ToolEquipInven:
|
||||
return InvenEquipType.Tool;
|
||||
|
||||
case EntityType.TattooEquipInven:
|
||||
return InvenEquipType.Tattoo;
|
||||
|
||||
default:
|
||||
Log.getLogger().error($"Invalid EntityType !!!, can't convert InvenEquipType : EntityType:{entityInvenType}");
|
||||
return InvenEquipType.None;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// 해당 가방에 장착 가능한 EItemLargeType 목록을 반환 한다.
|
||||
//=========================================================================================
|
||||
public static List<MetaAssets.EItemLargeType> toEquipableItemLargeTypes(this InvenBagType toEquipBagType)
|
||||
{
|
||||
switch (toEquipBagType)
|
||||
{
|
||||
case InvenBagType.Cloth:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.CLOTH };
|
||||
|
||||
case InvenBagType.Prop:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.PROP };
|
||||
|
||||
case InvenBagType.Beauty:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.BEAUTY };
|
||||
|
||||
case InvenBagType.Tattoo:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.TATTOO };
|
||||
|
||||
case InvenBagType.Etc:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.TOOL
|
||||
, MetaAssets.EItemLargeType.EXPENDABLE
|
||||
, MetaAssets.EItemLargeType.TICKET
|
||||
, MetaAssets.EItemLargeType.RAND_BOX
|
||||
, MetaAssets.EItemLargeType.SET_BOX
|
||||
};
|
||||
|
||||
default:
|
||||
Log.getLogger().error($"Invalid InvenBagType !!!, can't equip EItemLargeType : toEquipInvenBagType:{toEquipBagType}");
|
||||
return new List<MetaAssets.EItemLargeType>();
|
||||
}
|
||||
}
|
||||
|
||||
public static BagTabType toUsableBagTabType(this InvenBagType bagType)
|
||||
{
|
||||
switch (bagType)
|
||||
{
|
||||
case InvenBagType.Cloth:
|
||||
return BagTabType._1;
|
||||
|
||||
case InvenBagType.Prop:
|
||||
return BagTabType._2;
|
||||
|
||||
case InvenBagType.Beauty:
|
||||
return BagTabType._3;
|
||||
|
||||
case InvenBagType.Tattoo:
|
||||
return BagTabType._4;
|
||||
|
||||
case InvenBagType.Etc:
|
||||
return BagTabType._0;
|
||||
|
||||
default:
|
||||
Log.getLogger().error($"Invalid InvenBagType !!!, can't usable BagTabType : InvenBagType:{bagType}");
|
||||
return BagTabType.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static InvenBagType toUsableInvenBagType(this BagTabType bagType)
|
||||
{
|
||||
switch (bagType)
|
||||
{
|
||||
case BagTabType._1:
|
||||
return InvenBagType.Cloth;
|
||||
|
||||
case BagTabType._2:
|
||||
return InvenBagType.Prop;
|
||||
|
||||
case BagTabType._3:
|
||||
return InvenBagType.Beauty;
|
||||
|
||||
case BagTabType._4:
|
||||
return InvenBagType.Tattoo;
|
||||
|
||||
case BagTabType._0:
|
||||
return InvenBagType.Etc;
|
||||
|
||||
default:
|
||||
return InvenBagType.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static string toUsableInvenBagName(this BagTabType bagTabType)
|
||||
{
|
||||
var is_nft = false;
|
||||
|
||||
var inven_bag_type = InventoryRuleHelper.toUsableInvenBagType(bagTabType);
|
||||
if(InvenBagType.None == inven_bag_type)
|
||||
{
|
||||
if(BagTabType._5 <= bagTabType && bagTabType < BagTabType.MAX)
|
||||
{
|
||||
is_nft = true;
|
||||
|
||||
bagTabType -= (BagTabType.MAX - BagTabType._5);
|
||||
inven_bag_type = InventoryRuleHelper.toUsableInvenBagType(bagTabType);
|
||||
}
|
||||
}
|
||||
|
||||
var inven_bag_name = EnumHelper.convertEnumToEnumTypeAndValueString(inven_bag_type);
|
||||
|
||||
if (false == is_nft)
|
||||
{
|
||||
inven_bag_name += $"_NormalTab";
|
||||
}
|
||||
else
|
||||
{
|
||||
inven_bag_name += $"_NftTab";
|
||||
}
|
||||
|
||||
return inven_bag_name;
|
||||
}
|
||||
|
||||
public static BagTabType toNFTTabOffset(this BagTabType bagTabType, MetaAssets.ItemMetaData itemMeta)
|
||||
{
|
||||
return bagTabType + (true == itemMeta.IsNFT ? (BagTabType.MAX - BagTabType._5) : 0);
|
||||
}
|
||||
|
||||
public static EntityDynamoDbSortKeyType toEntitySKType(this InvenEquipType equipType)
|
||||
{
|
||||
switch (equipType)
|
||||
{
|
||||
case InvenEquipType.Cloth:
|
||||
return EntityDynamoDbSortKeyType.Guid;
|
||||
|
||||
case InvenEquipType.Tool:
|
||||
return EntityDynamoDbSortKeyType.Guid;
|
||||
|
||||
case InvenEquipType.Tattoo:
|
||||
return EntityDynamoDbSortKeyType.Guid;
|
||||
|
||||
default:
|
||||
Log.getLogger().error($"Invalid InvenEquipType !!!, can't use EntityDynamoDbSortKeyType : InvenEquipType:{equipType}");
|
||||
return EntityDynamoDbSortKeyType.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MetaAssets.EItemLargeType> toEquipableItemLargeTypes(this InvenEquipType equipType)
|
||||
{
|
||||
switch (equipType)
|
||||
{
|
||||
case InvenEquipType.Cloth:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.CLOTH };
|
||||
|
||||
case InvenEquipType.Tool:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.TOOL };
|
||||
|
||||
case InvenEquipType.Tattoo:
|
||||
return new List<MetaAssets.EItemLargeType>() { MetaAssets.EItemLargeType.TATTOO };
|
||||
|
||||
default:
|
||||
Log.getLogger().error($"Invalid InvenEquipType !!!, can't equip EItemLargeType : InvenEquipType:{equipType}");
|
||||
return new List<MetaAssets.EItemLargeType>();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MetaAssets.EItemSmallType> toEquipableItemSmallTypesWithClothSlotType(this InvenEquipType equipType, ClothSlotType clothSlotType)
|
||||
{
|
||||
switch (equipType)
|
||||
{
|
||||
case InvenEquipType.Cloth:
|
||||
return clothSlotType.toEquipableItemSmallTypes();
|
||||
|
||||
default:
|
||||
Log.getLogger().error($"Invalid InvenEquipType !!!, can't equip ClothSlotType : InvenEquipType:{equipType}, ClothSlotType:{clothSlotType}");
|
||||
return new List<MetaAssets.EItemSmallType>();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MetaAssets.EItemSmallType> toEquipableItemSmallTypes(this ClothSlotType clothSlotType)
|
||||
{
|
||||
var list = new List<EItemSmallType>();
|
||||
|
||||
foreach (var equipData in MetaData.Instance.Meta.ClothEquipTypeMetaTable.ClothEquipTypeDataList)
|
||||
{
|
||||
if (false == EnumHelper.tryParse<ClothSlotType>(equipData.EquipSlotType, out var slotType)) continue;
|
||||
if (slotType != clothSlotType) continue;
|
||||
if (false == EnumHelper.tryParse<EItemSmallType>(equipData.SmallType, out var smallType)) continue;
|
||||
list.Add(smallType);
|
||||
}
|
||||
|
||||
if (list.Count <= 0)
|
||||
{
|
||||
Log.getLogger().warn($"Invalid ClothSlotType !!!, can't equip ClothSlotType : ClothSlotType:{clothSlotType}");
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<ToolSlotType> toEquipableToolSlotTypes(this InvenEquipType equipType)
|
||||
{
|
||||
switch (equipType)
|
||||
{
|
||||
case InvenEquipType.Tool:
|
||||
return new List<ToolSlotType>() { ToolSlotType._1, ToolSlotType._2, ToolSlotType._3, ToolSlotType._4 };
|
||||
|
||||
default:
|
||||
Log.getLogger().error($"Invalid InvenEquipType !!!, can't equip ToolSlotType : InvenEquipType:{equipType}");
|
||||
return new List<ToolSlotType>();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<TattooSlotType> toEquipableTattooSlotTypes(this InvenEquipType equipType, EntityType entityType = EntityType.None)
|
||||
{
|
||||
switch (equipType)
|
||||
{
|
||||
case InvenEquipType.Tattoo:
|
||||
{
|
||||
if( EntityType.UgcNpc == entityType
|
||||
|| EntityType.Beacon == entityType )
|
||||
{
|
||||
return new List<TattooSlotType>() { TattooSlotType._1, TattooSlotType._2, TattooSlotType._3 };
|
||||
}
|
||||
|
||||
return new List<TattooSlotType>() { TattooSlotType._1, TattooSlotType._2, TattooSlotType._3, TattooSlotType._4 };
|
||||
}
|
||||
}
|
||||
|
||||
Log.getLogger().error($"Invalid InvenEquipType !!!, can't equip TattooSlotType : InvenEquipType:{equipType}");
|
||||
return new List<TattooSlotType>();
|
||||
}
|
||||
|
||||
public static bool isEquipableTattooSlotType(this InvenEquipType equipType, TattooSlotType slotType, EntityType entityType)
|
||||
{
|
||||
var equipable_slot_types = equipType.toEquipableTattooSlotTypes(entityType);
|
||||
var found_slot_type = equipable_slot_types.FirstOrDefault(x => x == slotType, TattooSlotType.None);
|
||||
if (TattooSlotType.None == found_slot_type)
|
||||
{
|
||||
var err_msg = $"Not found TattooSlotType !!! : InvenEquipType:{equipType}, TattooSlotType:{slotType} - entityType:{entityType}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ClothSlotType toClothSlotType(this MetaAssets.EItemSmallType smallType)
|
||||
{
|
||||
if (false == MetaData.Instance.Meta.ClothEquipTypeMetaTable.ClothEquipTypeDataListbyId.TryGetValue(smallType.ToString(), out var slotTypeData))
|
||||
{
|
||||
Log.getLogger().warn($"Invalid EItemSmallType !!!, can't convert ClothSlotType : EItemSmallType:{smallType}");
|
||||
return ClothSlotType.None;
|
||||
}
|
||||
|
||||
if (false == EnumHelper.tryParse<ClothSlotType>(slotTypeData.EquipSlotType, out var slotType))
|
||||
{
|
||||
Log.getLogger().warn($"Invalid EquipSlotType !!!, can't convert ClothSlotType : EquipSlotType:{slotTypeData.EquipSlotType}");
|
||||
return ClothSlotType.None;
|
||||
}
|
||||
|
||||
return slotType;
|
||||
}
|
||||
}
|
||||
234
ServerCommon/Helper/LoadBalanceServerHelper.cs
Normal file
234
ServerCommon/Helper/LoadBalanceServerHelper.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
using WORLD_META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class LoadBalanceServerHelper
|
||||
{
|
||||
private const int READ_SERVER_DATA_LIMIT_COUNT = 5;
|
||||
private const int FULL_LIMIT_RATE = 100;
|
||||
|
||||
public static async Task<ServerInfo?> getAuthLoginToChannelServerInfo( this IWithServerMetrics serverMetrics
|
||||
, EntityBase entityUser
|
||||
, UInt16 worldId = 0 )
|
||||
{
|
||||
if (0 >= worldId)
|
||||
{
|
||||
worldId = getWorldIdWenServerChange(entityUser);
|
||||
}
|
||||
|
||||
return await getBalancedServerInfo(serverMetrics, entityUser, ServerType.Channel, ServerMoveType.Auto, worldId);
|
||||
}
|
||||
|
||||
public static async Task<ServerInfo?> getReturnToServerInfo( this IWithServerMetrics serverMetrics
|
||||
, string toReturnServerName, ServerType toReturnServerType
|
||||
, EntityBase entityUser, ushort worldId = 0 )
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
|
||||
(var result, ServerInfo ? found_server_info) = await serverMetrics.getServerInfoByServerName(toReturnServerName);
|
||||
if (result.isSuccess() && null != found_server_info)
|
||||
{
|
||||
return found_server_info;
|
||||
}
|
||||
|
||||
found_server_info = await getBalancedServerInfo(serverMetrics, entityUser, toReturnServerType, ServerMoveType.Auto, worldId);
|
||||
if(null != found_server_info)
|
||||
{
|
||||
return found_server_info;
|
||||
}
|
||||
|
||||
err_msg = $"Not found ServerInfo !!!, in getReturnToServerInfo() : {result.toBasicString()} - {entityUser.toBasicString()}, {serverMetrics.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<ServerInfo?> getBalancedServerInfo( this IWithServerMetrics IWithServerMetrics
|
||||
, EntityBase entityUser
|
||||
, ServerType toServerType, ServerMoveType serverMoveType
|
||||
, UInt16 worldId = 0 )
|
||||
{
|
||||
string err_msg;
|
||||
|
||||
// 1. 모든 서버 리스트 가져오기
|
||||
var loaded_servers = await getAllServersPassableEntered(IWithServerMetrics, toServerType, worldId);
|
||||
if (!loaded_servers.Any())
|
||||
{
|
||||
err_msg = $"ServerMetrics count zero !!! toServerType:{toServerType}, worldId:{worldId} - {entityUser.toBasicString()}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 이동 타입에 따른 체크
|
||||
switch (serverMoveType)
|
||||
{
|
||||
case ServerMoveType.Auto:
|
||||
return await selectServerInfoFromList(loaded_servers.ToList(), entityUser, MetaHelper.GameConfigMeta.AutoMoveRate);
|
||||
case ServerMoveType.Force:
|
||||
return await selectServerInfoFromList(loaded_servers.ToList(), entityUser, FULL_LIMIT_RATE);
|
||||
case ServerMoveType.Return:
|
||||
case ServerMoveType.None:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<ServerInfo?> selectServerInfoFromList(IReadOnlyList<ServerInfo> servers, EntityBase entityUser, int limitRate)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
ServerInfo? select_server = null;
|
||||
ServerInfo? language_server = null;
|
||||
var check_user_count = -1;
|
||||
|
||||
var account_attribute = entityUser.getOriginEntityAttribute<AccountAttribute>();
|
||||
if (null == account_attribute) return null;
|
||||
|
||||
foreach (var server in servers)
|
||||
{
|
||||
var current_user_count = checkCurrentUserCount(server);
|
||||
|
||||
// 1. max count 체크
|
||||
var max_user_count = server.Capacity * limitRate / 100;
|
||||
if (max_user_count <= current_user_count) continue;
|
||||
|
||||
// 2. current session count 체크
|
||||
if (check_user_count >= current_user_count) continue;
|
||||
|
||||
select_server = server;
|
||||
check_user_count = current_user_count;
|
||||
}
|
||||
|
||||
return select_server ?? language_server;
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<ServerInfo>> getAllServersPassableEntered( this IWithServerMetrics serverMetrics
|
||||
, ServerType toServerType, WORLD_META_ID worldMetaId )
|
||||
{
|
||||
for (var i = 0; i < READ_SERVER_DATA_LIMIT_COUNT; i++)
|
||||
{
|
||||
// 1. 서버 정보 가져오기
|
||||
(var result, var found_server_infos) = await serverMetrics.getServerInfosByServerType(toServerType, worldMetaId);
|
||||
if (result.isFail())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. 서버 최대 세션수 체크
|
||||
// 서버의 최대 세션수보다 (현재 세션수 + 예약자 수 + 복귀자 수 + Beacon 수)가 크거나 같을때 목록에서 제외시킨다.
|
||||
found_server_infos.RemoveAll(x => checkCurrentUserCount(x) >= x.Capacity);
|
||||
|
||||
return found_server_infos;
|
||||
}
|
||||
|
||||
return new List<ServerInfo>();
|
||||
}
|
||||
|
||||
private static UInt16 getWorldIdWenServerChange(EntityBase entityUser)
|
||||
{
|
||||
UInt16 target_world_id = 0;
|
||||
|
||||
// 1. 기본 Default 정보 확인
|
||||
if (!MetaData.Instance._GameConfigMetaTable.TryGetValue(ConstantKeyType.DefaultEntryWorldIdWhenLoginToAuth.ToString(), out var found_value))
|
||||
{
|
||||
var err_msg = $"ConstantKeyType.DefaultEntryWorldIdWhenLoginToAuth not found !!! : worldId:{found_value} - {entityUser.toBasicString()}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. LastConnectionChannel 정보 확인
|
||||
var location_attribute = entityUser.getOriginEntityAttribute<LocationAttribute>();
|
||||
if (null == location_attribute) return target_world_id;
|
||||
|
||||
target_world_id = (location_attribute.LastestChannelServerLocation.WorldMetaId == 0)
|
||||
? Convert.ToUInt16(found_value)
|
||||
: (UInt16)location_attribute.LastestChannelServerLocation.WorldMetaId;
|
||||
|
||||
return target_world_id;
|
||||
}
|
||||
|
||||
private static int checkCurrentUserCount(ServerInfo server) => server.Sessions + server.Reservation + server.ReturnCount + server.UgcNpcCount;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// *인스턴스 룸을 생성할 인스턴스 서버 고르기*<br/>
|
||||
/// 인스턴스 룸 최대 인원이 들어갈 수 있는 서버 중 수용인원이 가장 많은 서버 선택
|
||||
/// </summary>
|
||||
/// <param name="serverList">인스턴스 서버 목록</param>
|
||||
/// <param name="roomCapacity">생성할 인스턴스 룸 최대 인원</param>
|
||||
/// <returns>입력값 List<ServerInfo> serverList 의 인덱스, 선택된 서버가 없는 경우 -1</returns>
|
||||
public static int getBestInstanceServerIndexForCreate(in List<ServerInfo> serverList, int roomCapacity)
|
||||
{
|
||||
int retIndex = -1;
|
||||
int maxCount = 0;
|
||||
|
||||
foreach (var (server_info, index) in serverList.Select((value, index) => (value, index)))
|
||||
{
|
||||
if (maxCount < server_info.RoomCapacity + roomCapacity && server_info.RoomCapacity + roomCapacity <= server_info.Capacity)
|
||||
{
|
||||
retIndex = index;
|
||||
maxCount = server_info.RoomCapacity + roomCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
return retIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// *게임 서버 고르기*<br/>
|
||||
/// 서버 수용인원의 80% 되지 않은 서버에서 선택<br/>
|
||||
/// 모든 서버가 80% 이상인 경우 서버 수용인원을 넘지 않은 서버에서 선택
|
||||
/// </summary>
|
||||
/// <param name="serverList">게임 서버 목록</param>
|
||||
/// <returns>입력값 List<ServerInfo> serverList 의 인덱스, 선택된 서버가 없는 경우 -1</returns>
|
||||
public static int getBestGameServerIndex(List<ServerInfo> serverList, LanguageType languageType
|
||||
, ref int currentServerIndex)
|
||||
{
|
||||
int server_index = -1;
|
||||
int limit_first = Constant.g_MaxUser * 5 / 10;
|
||||
|
||||
/*
|
||||
foreach (var serverInfo in serverList.Select((value, index) => new { value, index }))
|
||||
{
|
||||
if (serverInfo.value.Language == languageType &&
|
||||
limit_first > serverInfo.value.Sessions)
|
||||
{
|
||||
serverIndex = serverInfo.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (serverIndex == -1)
|
||||
{
|
||||
foreach (var serverInfo in serverList.Select((value, index) => new { value, index }))
|
||||
{
|
||||
if (limit_first > serverInfo.value.Sessions)
|
||||
{
|
||||
serverIndex = serverInfo.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (server_index == -1)
|
||||
{
|
||||
if (currentServerIndex >= serverList.Count)
|
||||
{
|
||||
currentServerIndex = 0;
|
||||
}
|
||||
|
||||
server_index = currentServerIndex;
|
||||
|
||||
++currentServerIndex;
|
||||
}
|
||||
|
||||
return server_index;
|
||||
}
|
||||
}
|
||||
92
ServerCommon/Helper/LocationHelper.cs
Normal file
92
ServerCommon/Helper/LocationHelper.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class LocationHelper
|
||||
{
|
||||
public static void clear(this ChannelServerLocation location)
|
||||
{
|
||||
location.SpawnPos = Vector3.Zero;
|
||||
location.ForwardAngle = 0.0f;
|
||||
location.ServerName = string.Empty;
|
||||
location.WorldMetaId = 0;
|
||||
}
|
||||
|
||||
public static void clear(this IndunLocation location)
|
||||
{
|
||||
location.SpawnPos = Vector3.Zero;
|
||||
location.ForwardAngle = 0.0f;
|
||||
location.InstanceMetaId = 0;
|
||||
location.InstanceRoomId = string.Empty;
|
||||
}
|
||||
|
||||
public static ChannelServerLocation clone(this ChannelServerLocation location)
|
||||
{
|
||||
ChannelServerLocation clone = new();
|
||||
|
||||
clone.SpawnPos = location.SpawnPos;
|
||||
clone.ForwardAngle = location.ForwardAngle;
|
||||
clone.ServerName = location.ServerName;
|
||||
clone.WorldMetaId = location.WorldMetaId;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static IndunLocation clone(this IndunLocation location)
|
||||
{
|
||||
IndunLocation clone = new();
|
||||
|
||||
clone.SpawnPos = location.SpawnPos;
|
||||
clone.ForwardAngle = location.ForwardAngle;
|
||||
clone.InstanceMetaId = location.InstanceMetaId;
|
||||
clone.InstanceRoomId = location.InstanceRoomId;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static void toPos(this BaseLoaction location, Pos pos)
|
||||
{
|
||||
pos.X = location.SpawnPos.X;
|
||||
pos.Y = location.SpawnPos.Y;
|
||||
pos.Z = location.SpawnPos.Z;
|
||||
pos.Angle = (int)location.ForwardAngle;
|
||||
}
|
||||
|
||||
public static void fromPos(this BaseLoaction location, Pos pos)
|
||||
{
|
||||
var newPos = new Vector3(pos.X, pos.Y, pos.Z);
|
||||
|
||||
location.SpawnPos = newPos;
|
||||
location.ForwardAngle = pos.Angle;
|
||||
}
|
||||
|
||||
public static Vector3 toVector3(this Pos pos)
|
||||
{
|
||||
Vector3 new_pos;
|
||||
|
||||
new_pos.X = pos.X;
|
||||
new_pos.Y = pos.Y;
|
||||
new_pos.Z = pos.Z;
|
||||
|
||||
return new_pos;
|
||||
}
|
||||
|
||||
public static Pos toPos(this Vector3 pos)
|
||||
{
|
||||
var new_pos = new Pos();
|
||||
|
||||
new_pos.X = pos.X;
|
||||
new_pos.Y = pos.Y;
|
||||
new_pos.Z = pos.Z;
|
||||
|
||||
return new_pos;
|
||||
}
|
||||
}
|
||||
42
ServerCommon/Helper/MessgaeHelper.cs
Normal file
42
ServerCommon/Helper/MessgaeHelper.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class MessgaeHelper
|
||||
{
|
||||
public static AvatarInfo toCharacterAppearanceProfile4Client( this CharacterAttribute.AppearanceProfile appearanceProfile )
|
||||
{
|
||||
var avatar_info = new AvatarInfo();
|
||||
var appearance_customize = new AppearanceCustomization();
|
||||
avatar_info.AppearCustomize = appearance_customize;
|
||||
|
||||
appearance_customize.BasicStyle = (int)appearanceProfile.BasicStyle;
|
||||
appearance_customize.BodyShape = (int)appearanceProfile.BodyShape;
|
||||
appearance_customize.HairStyle = (int)appearanceProfile.HairStyle;
|
||||
appearance_customize.CustomValues.AddRange(appearanceProfile.CustomValues.Select( x => x ).ToList());
|
||||
|
||||
avatar_info.Init = (uint)((true == appearanceProfile.IsCustomCompleted) ? 0 : 1);
|
||||
|
||||
|
||||
return avatar_info;
|
||||
}
|
||||
|
||||
public static AppearanceCustomization toCharacterAppearanceCustomize4Client(this CharacterAttribute.AppearanceProfile appearanceProfile)
|
||||
{
|
||||
var appearance_customize = new AppearanceCustomization();
|
||||
|
||||
appearance_customize.BasicStyle = (int)appearanceProfile.BasicStyle;
|
||||
appearance_customize.BodyShape = (int)appearanceProfile.BodyShape;
|
||||
appearance_customize.HairStyle = (int)appearanceProfile.HairStyle;
|
||||
appearance_customize.CustomValues.AddRange(appearanceProfile.CustomValues.Select(x => x).ToList());
|
||||
|
||||
return appearance_customize;
|
||||
}
|
||||
}
|
||||
663
ServerCommon/Helper/MetaHelper.cs
Normal file
663
ServerCommon/Helper/MetaHelper.cs
Normal file
@@ -0,0 +1,663 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Pipelines.Sockets.Unofficial.Buffers;
|
||||
using Amazon.DynamoDBv2.Model;
|
||||
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
using ENTITY_GUID = System.String;
|
||||
using ACCOUNT_ID = System.String;
|
||||
using OWNER_GUID = System.String;
|
||||
using USER_GUID = System.String;
|
||||
using CHARACTER_GUID = System.String;
|
||||
using ITEM_GUID = System.String;
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
//===========================================================================================
|
||||
// Meta 관련 각종 지원 함수
|
||||
//
|
||||
// author : kangms
|
||||
//
|
||||
//===========================================================================================
|
||||
|
||||
public static partial class MetaHelper
|
||||
{
|
||||
public static bool isTestAccount(this string accountId)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
// 1. TestUserCreateData Meta 파일에서 특정 계정 정보가 존재하는 지 체크 한다.
|
||||
if (true == MetaData.Instance.m_test_user_create_meta_datas.ContainsKey(accountId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task<(Result, MetaAssets.TestUserCreateMetaData?)> getTestUserCreateDataByAccountId(string accountId)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
// 1. TestUserCreateData Meta 파일에서 특정 계정 정보가 존재하는 지 체크 한다.
|
||||
if (false == MetaData.Instance.m_test_user_create_meta_datas.TryGetValue(accountId, out var found_test_user_create_data))
|
||||
{
|
||||
err_msg = $"Not found TestUserCreateData !!! : accountId:{accountId}";
|
||||
Log.getLogger().warn(err_msg);
|
||||
|
||||
// 1.1. TestUserCreateData Meta 파일에서 기본 계정 정보가 존재하는 지 체크 한다.
|
||||
if (false == MetaData.Instance.m_test_user_create_meta_datas.TryGetValue(MetaHelper.GameConfigMeta.DefaultTestAccountId, out found_test_user_create_data))
|
||||
{
|
||||
err_msg = $"Not found TestUserCreateData !!! : DefaultTestId:{MetaHelper.GameConfigMeta.DefaultTestAccountId} - accountId:{accountId}";
|
||||
result.setFail(ServerErrorCode.MetaDataNotFoundByTestUserId, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
return (result, found_test_user_create_data);
|
||||
}
|
||||
|
||||
public static async Task<(Result, MetaAssets.UserCreateMetaData?)> getUserCreateDataByAccountId(META_ID userCreateMetaId, string accountId)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
// 1. UserCreateData Meta 파일에서 특정 계정 정보가 존재하는 지 체크 한다.
|
||||
if (false == MetaData.Instance.m_user_create_meta_datas.TryGetValue((int)userCreateMetaId, out var found_user_create_data))
|
||||
{
|
||||
err_msg = $"Not found UserCreateData !!! : metaId:{userCreateMetaId} - accountId:{accountId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, found_user_create_data);
|
||||
}
|
||||
|
||||
public static async Task<(Result, AccountBaseDoc?)> fillupAccountBaseDocForAccountCreate(UserBase userBase, string accountId)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
// 1. AccountAttribute 기본 생성 정보를 설정 한다.
|
||||
var account_attribute = userBase.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {userBase.toBasicString()}");
|
||||
|
||||
account_attribute.AccountId = accountId;
|
||||
account_attribute.AccountCreationType = (accountId.isContainsBotId() == false ? AccountCreationType.Normal : AccountCreationType.Bot);
|
||||
account_attribute.newUserGuid(); // LoginCache 및 Game 시스템에서 유저 식별을 할 수 있도록 여기서 UserGuid를 미리 발급해 둔다 !!! - kangms
|
||||
account_attribute.LanguageType = LanguageType.Ko;
|
||||
account_attribute.newEntityAttribute();
|
||||
|
||||
// 2. AccountBaseDoc를 생성 한다.
|
||||
(result, var new_account_base_doc) = await account_attribute.toDocBase();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(new_account_base_doc, () => $"new_account_base_doc is null !!! - {userBase.toBasicString()}");
|
||||
|
||||
var account_base_attrib = new_account_base_doc.getAttrib<AccountBaseAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_base_attrib, () => $"account_base_attrib is null - {userBase.toBasicString()}");
|
||||
account_base_attrib.CreatedDateTime = DateTimeHelper.Current;
|
||||
|
||||
return (result, new_account_base_doc as AccountBaseDoc);
|
||||
}
|
||||
|
||||
public static async Task<(Result, AccountBaseDoc?)> fillupAccountBaseDocByTestUserCreateData(UserBase userBase, string accountId)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
AccountBaseDoc? new_account_base_doc;
|
||||
|
||||
try
|
||||
{
|
||||
// 1. TestUserCreateData Meta 파일에서 특정 계정 정보가 존재하는 지 체크 한다.
|
||||
(result, var found_test_user_create_data) = await getTestUserCreateDataByAccountId(accountId);
|
||||
if (result.isFail() || null == found_test_user_create_data)
|
||||
{
|
||||
err_msg = $"Not found TestUserCreateData for Account Create !!! : {result.toBasicString()} - accountId:{accountId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
// 1. AccountAttribute 기본 생성 정보를 설정 한다.
|
||||
var account_attribute = userBase.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {userBase.toBasicString()}");
|
||||
|
||||
account_attribute.AccountId = accountId;
|
||||
account_attribute.AccountCreationType = (accountId.isContainsBotId() == false ? AccountCreationType.Test : AccountCreationType.Bot);
|
||||
account_attribute.newUserGuid();// LoginCache 및 Game 시스템에서 유저 식별을 할 수 있도록 여기서 UserGuid를 미리 발급해 둔다 !!! - kangms
|
||||
account_attribute.newEntityAttribute();
|
||||
|
||||
if (false == account_attribute.copyEntityAttributeFromMeta(found_test_user_create_data))
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromMeta() !!! : to:{account_attribute.getTypeName()}, from:{found_test_user_create_data.getTypeName()} - accountId:{accountId}";
|
||||
result.setFail(ServerErrorCode.MetaDataCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
// 2. AccountBaseDoc를 생성 한다.
|
||||
(result, var maked_doc) = await account_attribute.toDocBase();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
new_account_base_doc = maked_doc as AccountBaseDoc;
|
||||
NullReferenceCheckHelper.throwIfNull(new_account_base_doc, () => $"new_account_base_doc is null - {userBase.toBasicString()}");
|
||||
var account_base_attrib = new_account_base_doc.getAttrib<AccountBaseAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_base_attrib, () => $"account_base_attrib is null - {userBase.toBasicString()}");
|
||||
account_base_attrib.CreatedDateTime = DateTimeHelper.Current;
|
||||
|
||||
// 3. AccountBaseDoc를 추가로 구성한다.
|
||||
// - TestUserCreateData => AccountBaseDoc 에 선택적으로 복사한다.
|
||||
result = await DataCopyHelper.copyDocFromMetas(new_account_base_doc, new List<MetaAssets.IMetaData>() { found_test_user_create_data });
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to copyDocFromMetas() !!! : accountId:{accountId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"Failed to fillupAccountBaseDocByTestUserCreateData() !!! : Exception:{e} - accountId:{accountId}";
|
||||
result.setFail(ServerErrorCode.DotNetException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, new_account_base_doc);
|
||||
}
|
||||
|
||||
public static async Task<(Result, UserBaseDoc?)> fillupUserBaseDocBy(UserBase userBase, AccountBaseDoc accountBaseDoc)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(userBase, () => $"userBase is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(accountBaseDoc, () => $"accountBaseDoc is null !!! - {userBase.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = userBase;
|
||||
|
||||
var account_attribute = owner.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {userBase.toBasicString()}");
|
||||
|
||||
var account_id = account_attribute.AccountId;
|
||||
|
||||
var user_attribute = owner.getEntityAttribute<UserAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {userBase.toBasicString()}");
|
||||
user_attribute.GameLoginDateTime = owner.getLoginStartTime();
|
||||
user_attribute.newEntityAttribute();
|
||||
|
||||
UserBaseDoc? user_base_doc_nullable;
|
||||
|
||||
try
|
||||
{
|
||||
if (false == user_attribute.copyEntityAttributeFromAccountBaseDoc(accountBaseDoc))
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromAccountBaseDoc() !!! : {accountBaseDoc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
(result, var user_doc_base) = await user_attribute.toDocBase();
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to toDocBase() !!! : {result.toBasicString()} - {user_attribute.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
user_base_doc_nullable = user_doc_base as UserBaseDoc;
|
||||
NullReferenceCheckHelper.throwIfNull(user_base_doc_nullable, () => $"user_base_doc_nullable is null - {userBase.toBasicString()}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"Failed to fillupUserBaseDocBy() !!! : Exception:{e} - userGuid:{user_attribute.UserGuid}, accountId:{account_id}";
|
||||
result.setFail(ServerErrorCode.DotNetException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, user_base_doc_nullable);
|
||||
}
|
||||
|
||||
public static async Task<(Result, CharacterBaseDoc?)> fillupCharacterBaseDocByTestUserCreateData(UserAttribute userAttribute, CharacterAttribute characterAttribute)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(userAttribute, () => $"userAttribute is null !!!");
|
||||
|
||||
var owner = userAttribute.getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(characterAttribute, () => $"characterAttribute is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var account_id = userAttribute.AccountId;
|
||||
var user_guid = userAttribute.UserGuid;
|
||||
|
||||
var new_character_base_doc = new CharacterBaseDoc();
|
||||
|
||||
try
|
||||
{
|
||||
// 1. TestUserCreateData Meta 파일에서 특정 계정 정보가 존재하는 지 체크 한다.
|
||||
(result, var found_test_user_create_data) = await getTestUserCreateDataByAccountId(account_id);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Not found TestUserCreateData for Character Create !!! : {result.toBasicString()} - accountId:{account_id}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_test_user_create_data, () => $"found_test_user_create_data is null !!! - {owner.toBasicString()}");
|
||||
|
||||
// 2. CharacterBaseDoc 를 구성 한다.
|
||||
if (false == characterAttribute.copyEntityAttributeFromMeta(found_test_user_create_data))
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromMeta() !!!, to:{characterAttribute.getTypeName()}, from:{found_test_user_create_data.getTypeName()}";
|
||||
result.setFail(ServerErrorCode.MetaDataCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
characterAttribute.newEntityAttribute();
|
||||
|
||||
(result, var character_doc) = await characterAttribute.toDocBase();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
new_character_base_doc = character_doc as CharacterBaseDoc;
|
||||
NullReferenceCheckHelper.throwIfNull(new_character_base_doc, () => $"new_character_base_doc is null !!! - {owner.toBasicString()}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"Failed to fillupCharacterBaseDocByTestUserCreateData() !!! : Exception:{e} - accountId:{account_id}, userGuid:{user_guid}";
|
||||
result.setFail(ServerErrorCode.DotNetException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, new_character_base_doc);
|
||||
}
|
||||
|
||||
public static async Task<(Result, CharacterBaseDoc?)> fillupCharacterBaseDocByUserCreateData( META_ID userCreateMetaId
|
||||
, UserAttribute userAttribute, CharacterAttribute characterAttribute)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(userAttribute, () => $"userAttribute is null !!!");
|
||||
|
||||
var owner = userAttribute.getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(characterAttribute, () => $"characterAttribute is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var account_id = userAttribute.AccountId;
|
||||
var user_guid = userAttribute.UserGuid;
|
||||
|
||||
var new_character_base_doc = new CharacterBaseDoc();
|
||||
|
||||
try
|
||||
{
|
||||
// 1. UserCreateData Meta 파일에서 특정 계정 정보가 존재하는 지 체크 한다.
|
||||
(result, var found_user_create_data) = await getUserCreateDataByAccountId(userCreateMetaId, account_id);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Not found serCreateData for Character Create !!! : {result.toBasicString()} - accountId:{account_id}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(found_user_create_data, () => $"found_user_create_data is null !!! - {owner.toBasicString()}");
|
||||
|
||||
// 2. CharacterBaseDoc 를 구성 한다.
|
||||
if (false == characterAttribute.copyEntityAttributeFromMeta(found_user_create_data))
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromMeta() !!!, to:{characterAttribute.getTypeName()}, from:{found_user_create_data.getTypeName()}";
|
||||
result.setFail(ServerErrorCode.MetaDataCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
characterAttribute.newEntityAttribute();
|
||||
|
||||
(result, var character_doc) = await characterAttribute.toDocBase();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
new_character_base_doc = character_doc as CharacterBaseDoc;
|
||||
NullReferenceCheckHelper.throwIfNull(new_character_base_doc, () => $"new_character_base_doc is null !!! - {owner.toBasicString()}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"Failed to fillupCharacterBaseDocByUserCreateData() !!! : Exception:{e} - accountId:{account_id}, userGuid:{user_guid}";
|
||||
result.setFail(ServerErrorCode.DotNetException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, new_character_base_doc);
|
||||
}
|
||||
|
||||
public static ClothInfo toClothInfo(this MetaAssets.TestUserCreateMetaData testUserCreateData, string userId)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
var cloth_info = new ClothInfo();
|
||||
|
||||
if (testUserCreateData.WearingItems == null)
|
||||
{
|
||||
return cloth_info;
|
||||
}
|
||||
|
||||
foreach (var item_meta_id in testUserCreateData.WearingItems)
|
||||
{
|
||||
MetaData.Instance._ItemTable.TryGetValue(item_meta_id, out var found_item_meta);
|
||||
if (null == found_item_meta)
|
||||
{
|
||||
err_msg = $"Not found Cloth Item in ItemData !!! : ItemMetaId:{item_meta_id} - userId:{userId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
var meta_id = (uint)found_item_meta.ItemId;
|
||||
|
||||
var error_code = found_item_meta.fillupClothInfo(ref cloth_info, userId);
|
||||
if (ServerErrorCode.Success != error_code)
|
||||
{
|
||||
err_msg = $"Failed to fillup ClothInfo !!! : errorCode:{error_code}, ItemMetaId:{item_meta_id} - TestUserCreateMetaId:{testUserCreateData.MetaId}, userId:{userId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return cloth_info;
|
||||
}
|
||||
|
||||
public static ServerErrorCode fillupClothInfo(this MetaAssets.ItemMetaData metaData, ref ClothInfo clothInfo, string userId)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(clothInfo, () => $"clothInfo is null !!!");
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (null == clothInfo)
|
||||
{
|
||||
err_msg = $"Function param is null, ClothInfo !!! : ItemMetaId:{metaData.ItemId} - userId:{userId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return ServerErrorCode.FunctionParamNull;
|
||||
}
|
||||
|
||||
var meta_id = (uint)metaData.ItemId;
|
||||
|
||||
if (false == metaData.TypeLarge.isClothType())
|
||||
{
|
||||
err_msg = $"Not EItemLargeType of Cloth !!! : EItemLargeType.Cloth == {metaData.TypeLarge}, ItemMetaId:{meta_id} - userId:{userId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return ServerErrorCode.ItemClothInvalidLargeType;
|
||||
}
|
||||
|
||||
if (false == metaData.TypeSmall.isClothType())
|
||||
{
|
||||
err_msg = $"Not EItemSmallType of Cloth !!! : EItemSmallType:{metaData.TypeSmall}, ItemMetaId:{meta_id} - userId:{userId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return ServerErrorCode.ItemClothInvalidSmallType;
|
||||
}
|
||||
|
||||
clothInfo.setClothInfo(metaData, userId);
|
||||
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
public static bool isClothType(this MetaAssets.ItemMetaData itemMeta)
|
||||
{
|
||||
if (true == itemMeta.TypeLarge.isClothType()
|
||||
&& true == itemMeta.TypeSmall.isClothType())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool isClothType(this MetaAssets.EItemLargeType itemLargeType)
|
||||
{
|
||||
if (MetaAssets.EItemLargeType.CLOTH == itemLargeType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool isClothType(this MetaAssets.EItemSmallType itemSmallType)
|
||||
{
|
||||
switch (itemSmallType)
|
||||
{
|
||||
case MetaAssets.EItemSmallType.CAP:
|
||||
case MetaAssets.EItemSmallType.MASK:
|
||||
case MetaAssets.EItemSmallType.GLASSES:
|
||||
case MetaAssets.EItemSmallType.EARRING:
|
||||
case MetaAssets.EItemSmallType.NECKLACE:
|
||||
case MetaAssets.EItemSmallType.SHIRT:
|
||||
case MetaAssets.EItemSmallType.DRESS:
|
||||
case MetaAssets.EItemSmallType.PANTS:
|
||||
case MetaAssets.EItemSmallType.SOCKS:
|
||||
case MetaAssets.EItemSmallType.ANKLET:
|
||||
case MetaAssets.EItemSmallType.GLOVES:
|
||||
case MetaAssets.EItemSmallType.BRACELET:
|
||||
case MetaAssets.EItemSmallType.RING:
|
||||
case MetaAssets.EItemSmallType.SHOES:
|
||||
case MetaAssets.EItemSmallType.OUTER:
|
||||
case MetaAssets.EItemSmallType.BACKPACK:
|
||||
case MetaAssets.EItemSmallType.BAG:
|
||||
case MetaAssets.EItemSmallType.SHOULDERBAG:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool setClothInfo(this ClothInfo clothInfo, MetaAssets.ItemMetaData itemMeta, string userId)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(itemMeta, () => $"itemMeta is null !!!");
|
||||
|
||||
var meta_id = (uint)itemMeta.ItemId;
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
switch (itemMeta.TypeSmall)
|
||||
{
|
||||
case MetaAssets.EItemSmallType.CAP:
|
||||
clothInfo.ClothHeadwear = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.MASK:
|
||||
case MetaAssets.EItemSmallType.GLASSES:
|
||||
clothInfo.ClothMask = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.EARRING:
|
||||
clothInfo.ClothEarrings = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.NECKLACE:
|
||||
clothInfo.ClothNeckless = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.SHIRT:
|
||||
case MetaAssets.EItemSmallType.DRESS:
|
||||
clothInfo.ClothTops = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.PANTS:
|
||||
clothInfo.ClothBottoms = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.SOCKS:
|
||||
case MetaAssets.EItemSmallType.ANKLET:
|
||||
clothInfo.ClothSocks = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.GLOVES:
|
||||
case MetaAssets.EItemSmallType.BRACELET:
|
||||
case MetaAssets.EItemSmallType.RING:
|
||||
clothInfo.ClothGloves = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.SHOES:
|
||||
clothInfo.ClothShoes = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.OUTER:
|
||||
clothInfo.ClothOuter = meta_id;
|
||||
break;
|
||||
case MetaAssets.EItemSmallType.BACKPACK:
|
||||
case MetaAssets.EItemSmallType.BAG:
|
||||
case MetaAssets.EItemSmallType.SHOULDERBAG:
|
||||
clothInfo.ClothBag = meta_id;
|
||||
break;
|
||||
|
||||
default:
|
||||
err_msg = $"No EItemSmallType in ClothInfo !!! : EItemSmallType:{itemMeta.TypeSmall}, ItemMetaId:{meta_id} - userId:{userId}";
|
||||
Log.getLogger().warn(err_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool isTattooType(this MetaAssets.ItemMetaData itemMeta)
|
||||
{
|
||||
if (true == itemMeta.TypeLarge.isTattooType())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool isTattooType(this MetaAssets.EItemLargeType itemLargeType)
|
||||
{
|
||||
if (itemLargeType == MetaAssets.EItemLargeType.TATTOO)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static CurrencyType toCurrencyType(this EntityDeltaType deltaType)
|
||||
{
|
||||
return deltaType switch
|
||||
{
|
||||
EntityDeltaType.MoneyGold => CurrencyType.Gold,
|
||||
EntityDeltaType.MoneySaphire => CurrencyType.Sapphire,
|
||||
EntityDeltaType.MoneyCalium => CurrencyType.Calium,
|
||||
EntityDeltaType.MoneyBeam => CurrencyType.Beam,
|
||||
EntityDeltaType.MoneyRuby => CurrencyType.Ruby,
|
||||
_ => CurrencyType.None
|
||||
};
|
||||
}
|
||||
|
||||
public static CurrencyType intToCurrencyType(int currencyType)
|
||||
{
|
||||
return currencyType switch
|
||||
{
|
||||
1 => CurrencyType.Gold,
|
||||
2 => CurrencyType.Sapphire,
|
||||
3 => CurrencyType.Calium,
|
||||
4 => CurrencyType.Beam,
|
||||
5 => CurrencyType.Ruby,
|
||||
_ => CurrencyType.None
|
||||
};
|
||||
}
|
||||
|
||||
public static bool isBalanceWithinMaxCurrency(this CurrencyType currencyType, double currencyValue)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
// 해당 CurrencyType 으로 등록되어 있지 않아도 실패 처리 한다. !!!
|
||||
if (MetaData.Instance._CurrencyMetaTableByCurrencyType.TryGetValue(currencyType, out var currencyMetaData) == false)
|
||||
{
|
||||
err_msg = $"Not found CurrencyMetaData !!! : currencyType:{currencyType}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 제한 크기를 초과하면 실패 처리 한다. !!!
|
||||
if(currencyMetaData.MaxCount < currencyValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<MailItem> toMailItems(List<MetaAssets.GachaMetaData> gachaMetaDatas)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(gachaMetaDatas, () => $"gachaMetaDatas is null !!!");
|
||||
|
||||
var mail_items = new List<MailItem>();
|
||||
|
||||
foreach(var gachaMetaData in gachaMetaDatas)
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(gachaMetaData, () => $"gachaMetaData is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(gachaMetaData.Reward, () => $"gachaMetaData.Reward is null !!!");
|
||||
|
||||
if (gachaMetaData.Reward.Item is MetaAssets.ItemReward reward_item)
|
||||
{
|
||||
var mail_item = new MailItem();
|
||||
mail_item.ItemId = (META_ID)reward_item.Id;
|
||||
mail_item.Count = reward_item.Count;
|
||||
|
||||
mail_items.Add(mail_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
object? reward_type = null;
|
||||
if (gachaMetaData.Reward.Currency is MetaAssets.CurrencyReward reward_currency)
|
||||
{
|
||||
reward_type = reward_currency;
|
||||
}
|
||||
|
||||
Log.getLogger().error($"Not supported RewardType in Mail !!! : {reward_type?.getTypeName() ?? string.Empty} - gachaMetaId:{gachaMetaData.Id}");
|
||||
}
|
||||
}
|
||||
|
||||
return mail_items;
|
||||
}
|
||||
}
|
||||
76
ServerCommon/Helper/MetaTextStringHelper.cs
Normal file
76
ServerCommon/Helper/MetaTextStringHelper.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
using FUNCTION_NAME = System.String;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class MetaTextStringHelper
|
||||
{
|
||||
public delegate string META_TEXT_STRING_FUNC(object caller, params object[] parameters);
|
||||
|
||||
private static readonly Dictionary<FUNCTION_NAME, META_TEXT_STRING_FUNC> m_methods = new();
|
||||
|
||||
// 초기 입력 문자열 저장
|
||||
private static string m_input_string = string.Empty;
|
||||
private static StringBuilder m_result_builder = new StringBuilder();
|
||||
|
||||
public static bool parseAndExecute(string funcName, object caller, params object[] parameters)
|
||||
{
|
||||
// 등록된 함수가 있는지 확인
|
||||
if (m_methods.ContainsKey(funcName))
|
||||
{
|
||||
string func_result = m_methods[funcName](caller, parameters); // 함수 실행
|
||||
// {순번: 함수명} 패턴을 찾아 함수 결과로 대체
|
||||
string pattern = $@"\{{\d+\s*:\s*{funcName}\}}";
|
||||
|
||||
// 패턴을 찾고 함수 결과로 대체
|
||||
m_result_builder = new StringBuilder(Regex.Replace(m_result_builder.ToString(), pattern, func_result));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void inputString(string input)
|
||||
{
|
||||
m_input_string = input;
|
||||
m_result_builder = new StringBuilder(input); // 입력 문자열로 초기화
|
||||
}
|
||||
|
||||
public static string getResult()
|
||||
{
|
||||
return m_result_builder.ToString();
|
||||
}
|
||||
|
||||
public static bool registerFunc(string name, META_TEXT_STRING_FUNC func)
|
||||
{
|
||||
if (true == m_methods.ContainsKey(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_methods[name] = func;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 문자열 내에 {순번: 함수명} 구조가 존재하는지 확인해주는 함수 !!!, 존재할 경우 true 반환 한다.
|
||||
public static bool isContainsMetaTextStringFunctionPattern(string input)
|
||||
{
|
||||
// {숫자: 함수명} 구조를 찾는 정규 표현식을 설정 한다.
|
||||
var pattern = @"\{\d+\s*:\s*[a-zA-Z_]\w*\}";
|
||||
|
||||
// 정규 표현식으로 입력 문자열에서 해당 패턴이 존재하는지 확인 한다. !!!
|
||||
return Regex.IsMatch(input, pattern);
|
||||
}
|
||||
}
|
||||
126
ServerCommon/Helper/MyHomeHelper.cs
Normal file
126
ServerCommon/Helper/MyHomeHelper.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using Amazon.S3.Model;
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class MyHomeHelper
|
||||
{
|
||||
public static async Task<Result> uploadMyhomeUgcInfo( this S3ConnectorBase s3connector
|
||||
, string bucketName
|
||||
, string myhomeUgcInfoS3Key, string myhomeUgcInfo )
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
using (var memory_stream = myhomeUgcInfo.toStream())
|
||||
{
|
||||
var request = new PutObjectRequest
|
||||
{
|
||||
BucketName = bucketName,
|
||||
Key = myhomeUgcInfoS3Key,
|
||||
InputStream = memory_stream,
|
||||
};
|
||||
|
||||
if (false == await s3connector.uploadFile(request))
|
||||
{
|
||||
err_msg = $"Failed to uploadFile() !!!";
|
||||
result.setFail(ServerErrorCode.S3FileUploadFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<Result> deleteMyhomeUgcInfo( this S3ConnectorBase s3connector
|
||||
, string bucketName
|
||||
, string myhomeUgcInfoS3Key)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var request = new DeleteObjectRequest
|
||||
{
|
||||
BucketName = bucketName,
|
||||
Key = myhomeUgcInfoS3Key,
|
||||
};
|
||||
|
||||
if (!await s3connector.deleteFile(request))
|
||||
{
|
||||
err_msg = $"Failed to deleteFile() !!!";
|
||||
result.setFail(ServerErrorCode.S3FileDeleteFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<Result> deleteMyhomeUgcInfoFolderFile( this S3ConnectorBase s3connector
|
||||
, string bucketName
|
||||
, string myhomeGuid )
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var request = new ListObjectsV2Request
|
||||
{
|
||||
BucketName = bucketName,
|
||||
Prefix = myhomeGuid,
|
||||
};
|
||||
|
||||
if (!await s3connector.deleteFolderFile(request))
|
||||
{
|
||||
err_msg = $"Failed to deleteFile() !!!";
|
||||
result.setFail(ServerErrorCode.S3FileDeleteFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<(Result, string)> getMyhomeUgcInfo( this S3ConnectorBase s3connector
|
||||
, string bucketName
|
||||
, string myhomeUgcInfoS3Key )
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var myhome_ugc_info = string.Empty;
|
||||
|
||||
var request = new GetObjectRequest
|
||||
{
|
||||
BucketName = bucketName,
|
||||
Key = myhomeUgcInfoS3Key,
|
||||
};
|
||||
|
||||
(var is_success, var stream) = await s3connector.getFileStream(request);
|
||||
if ( false == is_success
|
||||
|| null == stream )
|
||||
{
|
||||
err_msg = $"Failed to getFile() !!! - bucketName:{bucketName}, key:{myhomeUgcInfoS3Key}";
|
||||
result.setFail(ServerErrorCode.S3FileGetFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, myhome_ugc_info);
|
||||
}
|
||||
|
||||
myhome_ugc_info = stream.toString();
|
||||
|
||||
return (result, myhome_ugc_info);
|
||||
}
|
||||
}
|
||||
104
ServerCommon/Helper/QuestHelper.cs
Normal file
104
ServerCommon/Helper/QuestHelper.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
using UGQDatabase.Models;
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
|
||||
public static class QuestHelper
|
||||
{
|
||||
|
||||
public static (UInt32, UInt32) convertUgqQuestIdToQuestIdAndRevision(Int64 ugq_quest_id)
|
||||
{
|
||||
var quest_id = (UInt32)(ugq_quest_id & 0xFFFFFFFF);
|
||||
var quest_revision = (UInt32)(ugq_quest_id >> 32);
|
||||
return (quest_id, quest_revision);
|
||||
}
|
||||
|
||||
public static Int64 convertQuestIdAndRevisionToUgqQuestId(UInt32 quest_id, UInt32 quest_revision)
|
||||
{
|
||||
Int64 ugq_quest_id = ((Int64)quest_revision << 32) | quest_id;
|
||||
return ugq_quest_id;
|
||||
}
|
||||
|
||||
public static UgqStateType convertQuestContentStateToUgqStateType(QuestContentState state)
|
||||
{
|
||||
|
||||
//RevisionChanged 이건 어디다 쓰지?
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case QuestContentState.None:
|
||||
case QuestContentState.Editable:
|
||||
case QuestContentState.Shutdown:
|
||||
case QuestContentState.Standby:
|
||||
return UgqStateType.Shutdown;
|
||||
case QuestContentState.Test:
|
||||
return UgqStateType.Test;
|
||||
case QuestContentState.Live:
|
||||
return UgqStateType.Live;
|
||||
default:
|
||||
return UgqStateType.Shutdown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static QuestContentState convertUgqStateTypeToQuestContentState(UgqStateType state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case UgqStateType.Test:
|
||||
return QuestContentState.Test;
|
||||
case UgqStateType.Live:
|
||||
return QuestContentState.Live;
|
||||
case UgqStateType.Shutdown:
|
||||
case UgqStateType.None:
|
||||
return QuestContentState.None;
|
||||
default:
|
||||
return QuestContentState.None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static string convertUgqGradeToQuestCheckGrade(UgqGradeType gradeType)
|
||||
{
|
||||
switch (gradeType)
|
||||
{
|
||||
case UgqGradeType.Amature:
|
||||
return QuestUgqGradeConditionType.AMATEUR.ToString();
|
||||
case UgqGradeType.RisingStar:
|
||||
return QuestUgqGradeConditionType.RISINGSTAR.ToString();
|
||||
case UgqGradeType.Master1:
|
||||
return QuestUgqGradeConditionType.MASTER1.ToString();
|
||||
case UgqGradeType.Master2:
|
||||
return QuestUgqGradeConditionType.MASTER2.ToString();
|
||||
case UgqGradeType.Master3:
|
||||
return QuestUgqGradeConditionType.MASTER3.ToString();
|
||||
case UgqGradeType.None:
|
||||
return QuestUgqGradeConditionType.ALL.ToString();
|
||||
default:
|
||||
return QuestUgqGradeConditionType.ALL.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum QuestUgqGradeConditionType
|
||||
{
|
||||
ALL = 1,
|
||||
AMATEUR = 2,
|
||||
RISINGSTAR = 3,
|
||||
MASTER1 = 4,
|
||||
MASTER2 = 5,
|
||||
MASTER3 = 6,
|
||||
}
|
||||
176
ServerCommon/Helper/ServerConnectionSwitchHelper.cs
Normal file
176
ServerCommon/Helper/ServerConnectionSwitchHelper.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Nettention.Proud;
|
||||
using Newtonsoft.Json;
|
||||
using OtpNet;
|
||||
using Pipelines.Sockets.Unofficial.Buffers;
|
||||
using StackExchange.Redis;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
using SESSION_ID = System.Int32;
|
||||
using META_ID = System.UInt32;
|
||||
using ENTITY_GUID = System.String;
|
||||
using ACCOUNT_ID = System.String;
|
||||
using OWNER_GUID = System.String;
|
||||
using USER_GUID = System.String;
|
||||
using CHARACTER_GUID = System.String;
|
||||
using ITEM_GUID = System.String;
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class ServerConnectionSwitchHelper
|
||||
{
|
||||
public static async Task<Result> registerUserOtpToTargetServer(UserBase entityUser, RedisConnector redisConnector
|
||||
, string destServer)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
(result, var reserved_to_switch_server) = await startServerSwitch(entityUser, redisConnector, destServer);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(reserved_to_switch_server, () => $"reserved_to_switch_server is null !!!");
|
||||
|
||||
var account_attribute = entityUser.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {entityUser.toBasicString()}");
|
||||
|
||||
account_attribute.OtpForServerConnect = reserved_to_switch_server.OneTimeKey;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<(Result, LoginCache.ReservationToSwitchServer?)> startServerSwitch(UserBase entityUser, RedisConnector redisConnector, string destServer)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var login_cache_request = new LoginCacheRequest(entityUser, redisConnector);
|
||||
result = await login_cache_request.onPrepareRequest();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
string key = login_cache_request.getKey();
|
||||
var database = login_cache_request.getDatabase();
|
||||
|
||||
var value = await database.StringGetAsync(key, CommandFlags.PreferReplica);
|
||||
if (value.HasValue == false)
|
||||
{
|
||||
err_msg = $"Not found Key !!! : Key:{key} - {entityUser.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.RedisLoginCacheGetFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var login_cache = JsonConvert.DeserializeObject<LoginCache>(value.ToString());
|
||||
if (null == login_cache)
|
||||
{
|
||||
err_msg = $"Failed to JsonConvert.DeserializeObject !!! : {login_cache_request.toBasicString()} - {entityUser.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.JsonConvertDeserializeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var otp = KeyGeneration.GenerateRandomKey(20);
|
||||
var otp_encoding_by_base32 = Base32Encoding.ToString(otp);
|
||||
|
||||
login_cache.ReservedToSwitchServer = new LoginCache.ReservationToSwitchServer()
|
||||
{
|
||||
OneTimeKey = otp_encoding_by_base32,
|
||||
DestServer = destServer
|
||||
};
|
||||
|
||||
var json_string = login_cache.toJsonString();
|
||||
|
||||
if (await database.StringSetAsync(key, json_string, TimeSpan.FromMilliseconds(LoginCacheRequest.SERVER_SWITCH_CACHE_EXPIRY_TIME)) == false)
|
||||
{
|
||||
err_msg = $"Failed to StringSetAsync !!! : Key:{key}, JsonString:{json_string} - {entityUser.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.RedisStringsWriteFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
Log.getLogger().info($"Server Switching Start : currServer:{login_cache.CurrentServer}, destServer:{destServer} - {entityUser.toBasicString()}");
|
||||
|
||||
return (result, login_cache.ReservedToSwitchServer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"Failed to startServerSwitch !!! : Exception:{e} - {entityUser.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.TryCatchException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<Result> endServerSwitch(EntityBase entityUser, LoginCacheRequest loginCacheRequest
|
||||
, string currConnectedServer
|
||||
, DateTime switchedDateTime)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var database = loginCacheRequest.getDatabase();
|
||||
var login_cache = loginCacheRequest.getLoginCache();
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(login_cache, () => $"login_cache is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(login_cache.ReservedToSwitchServer, () => $"login_cache.ReservedToSwitchServer is null !!!");
|
||||
|
||||
string prev_connected_server = login_cache.CurrentServer;
|
||||
|
||||
login_cache.LoginDateTime = switchedDateTime;
|
||||
|
||||
login_cache.ServerSwitchCount += 1;
|
||||
login_cache.CurrentServer = login_cache.ReservedToSwitchServer.DestServer;
|
||||
login_cache.ReservedToSwitchServer = null;
|
||||
|
||||
var key = loginCacheRequest.getKey();
|
||||
var json_string = login_cache.toJsonString();
|
||||
|
||||
if (await database.StringSetAsync(key, json_string, TimeSpan.FromMilliseconds(LoginCacheRequest.LOGIN_CACHE_EXPIRY_TIME)) == false)
|
||||
{
|
||||
err_msg = $"Failed to StringSetAsync !!! : Key:{key}, JsonString:{json_string} - {entityUser.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.RedisStringsWriteFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Log.getLogger().info($"Server Switching End : prevServer:{prev_connected_server} => currServer:{currConnectedServer} - {entityUser.toBasicString()}");
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"Failed to startServerSwitch !!! : Exception:{e} - {entityUser.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.TryCatchException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
ServerCommon/Helper/ServerHelper.cs
Normal file
18
ServerCommon/Helper/ServerHelper.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using ServerCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class ServerHelper
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
56
ServerCommon/Helper/ServerLogicHelper.cs
Normal file
56
ServerCommon/Helper/ServerLogicHelper.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
using MODULE_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class ServerLogicHelper
|
||||
{
|
||||
public static Result loadMetaDatas(this ServerLogicBase serverLogicBase)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (false == MetaData.Instance.LoadTableAll())
|
||||
{
|
||||
err_msg = $"Failed to LoadTableAll()!!! : {serverLogicBase.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MetaDataLoadFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static ProudNetListener getProudNetListener(this ServerLogicBase serverLogicBase)
|
||||
{
|
||||
var found_proud_net_listener = ServerBase.ServerLogicHelper.getListenSessionBase(serverLogicBase) as ProudNetListener;
|
||||
NullReferenceCheckHelper.throwIfNull(found_proud_net_listener, () => $"found_proud_net_listener is null !!! - {serverLogicBase.toBasicString()}");
|
||||
return found_proud_net_listener;
|
||||
}
|
||||
|
||||
public static ILogActor toLogActor(this ServerLogicBase serverLogicBase)
|
||||
{
|
||||
var log_info = new LogicActorLog();
|
||||
|
||||
log_info.initLogInfo(
|
||||
serverLogicBase.getServerConfig().getRegionId()
|
||||
, serverLogicBase.getServerConfig().getWorldId()
|
||||
, serverLogicBase.getServerType().toServerType()
|
||||
, serverLogicBase.getServerName()
|
||||
);
|
||||
|
||||
return log_info;
|
||||
}
|
||||
}
|
||||
46
ServerCommon/Helper/ServerMetricsHelper.cs
Normal file
46
ServerCommon/Helper/ServerMetricsHelper.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
using WORLD_META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class ServerMetricsHelper
|
||||
{
|
||||
public static async Task<(Result, List<ServerInfo>)> getServerInfoAll(this IWithServerMetrics serverMetrics)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var server_metrics_request = serverMetrics.getServerMetricsCacheRequest();
|
||||
NullReferenceCheckHelper.throwIfNull(server_metrics_request, () => $"server_metrics_request is null - {serverMetrics.toBasicString()}");
|
||||
var handler_type = (uint)ServerMetricsCacheRequest.TriggerType.ServerMetrics_AllGetAndFill;
|
||||
var world_meta_ids = new List<WORLD_META_ID>();
|
||||
foreach (var worldData in MetaData.Instance._WorldMetaTable)
|
||||
{
|
||||
world_meta_ids.Add((WORLD_META_ID)worldData.Value.Id);
|
||||
}
|
||||
|
||||
var with_result = await server_metrics_request.tryRunTriggerHandler(handler_type, world_meta_ids);
|
||||
if (with_result.Result.isFail())
|
||||
{
|
||||
return (with_result.Result, new List<ServerInfo>());
|
||||
}
|
||||
if (with_result.isResultOnly())
|
||||
{
|
||||
return (result, new List<ServerInfo>());
|
||||
}
|
||||
|
||||
var result_value_server_info = with_result as ResultValue<List<ServerInfo>>;
|
||||
NullReferenceCheckHelper.throwIfNull(result_value_server_info, () => $"result_value_server_info is null - {serverMetrics.toBasicString()}");
|
||||
|
||||
return (result, result_value_server_info.ValueOfResult);
|
||||
}
|
||||
}
|
||||
107
ServerCommon/Helper/StringRuleHelper.cs
Normal file
107
ServerCommon/Helper/StringRuleHelper.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class StringRuleHelper
|
||||
{
|
||||
public static ServerErrorCode isValidNickname(string nickName)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(nickName, () => $"stringValue is null");
|
||||
|
||||
// 첫번째 글자가 숫자인지 체크 한다.
|
||||
if (Regex.IsMatch(nickName[0].ToString(), "[0-9]") == true)
|
||||
{
|
||||
return ServerErrorCode.UserNicknameNotAllowedNumberAtFirstChars;
|
||||
}
|
||||
|
||||
// 특수문자가 포함되어 있는지 체크 한다.
|
||||
if (true == nickName.isContainSpecialChars(out _))
|
||||
{
|
||||
return ServerErrorCode.UserNicknameNotAllowWithSpecialChars;
|
||||
}
|
||||
|
||||
// 길이 체크
|
||||
if ( nickName.Length < MetaHelper.GameConfigMeta.UserNicknameMinLength ||
|
||||
nickName.Length > MetaHelper.GameConfigMeta.UserNicknameMaxLength )
|
||||
{
|
||||
return ServerErrorCode.UserNicknameAllowedMin2ToMax12;
|
||||
}
|
||||
|
||||
// 금지어 여부를 체크 한다.
|
||||
if (StringRuleHelper.isBanNickname(nickName) == true)
|
||||
{
|
||||
Log.getLogger().info($"User Nickname is Ban !!! : nickname:{nickName}");
|
||||
return ServerErrorCode.UserNicknameBan;
|
||||
}
|
||||
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
public static string convertStringFromBase64(string stringValue)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(stringValue, () => $"stringValue is null");
|
||||
|
||||
string decoded_text = string.Empty;
|
||||
try
|
||||
{
|
||||
byte[] byteArray = Convert.FromBase64String(stringValue);
|
||||
decoded_text = Encoding.UTF8.GetString(byteArray);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.getLogger().error($"convertStringFromBase64 exception occured {e.StackTrace}");
|
||||
}
|
||||
|
||||
return decoded_text;
|
||||
}
|
||||
|
||||
public static string getString(LanguageType langType, List<OperationSystemMessage> systemMessage)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(systemMessage, () => $"systemMessage is null");
|
||||
|
||||
string txt = string.Empty;
|
||||
foreach (var msg in systemMessage)
|
||||
{
|
||||
if ((int)msg.LanguageType == (int)langType)
|
||||
{
|
||||
//var base64_string = StringRuleHelper.convertStringFromBase64(msg.Text);
|
||||
txt = msg.Text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return txt;
|
||||
}
|
||||
|
||||
public static bool isBanWord(string word, bool includeNickname)
|
||||
{
|
||||
var lowered_word = word.ToLower();
|
||||
|
||||
if (MetaData.Instance._BanWordMetaTable.Any(banWord => lowered_word.Contains(banWord) == true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return includeNickname && isBanNickname(word);
|
||||
}
|
||||
|
||||
private static bool isBanNickname(string word)
|
||||
{
|
||||
var lowered_word = word.ToLower();
|
||||
|
||||
return MetaData.Instance._BanWordNicknameMetaTable.Any(banNickNameWord => lowered_word.Contains(banNickNameWord) == true);
|
||||
}
|
||||
}
|
||||
74
ServerCommon/Helper/TransactionRunnerHelper.cs
Normal file
74
ServerCommon/Helper/TransactionRunnerHelper.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class TransactionRunnerHelper
|
||||
{
|
||||
|
||||
public static async Task onApplyCommonResultOfInsertedItem( this TransactionRunner transactionRunner
|
||||
, ItemBase insertedItemInBag )
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var owner = transactionRunner.getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(insertedItemInBag, () => $"insertedItemInBag is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var item_attribute_base = insertedItemInBag.getEntityAttribute<ItemAttributeBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {owner.toBasicString()}");
|
||||
|
||||
(var result, var entity_common_result) = transactionRunner.getOrNewEntityCommonResult(item_attribute_base);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().fatal(result.toBasicString());
|
||||
|
||||
// 유저 로그 아웃 처리 필요 !!!
|
||||
return;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(entity_common_result, () => $"entity_common_result is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var item_result = entity_common_result.Item;
|
||||
NullReferenceCheckHelper.throwIfNull(item_result, () => $"item_result is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var item_guid = item_attribute_base.ItemGuid;
|
||||
item_result.NewItems.TryAdd(item_guid, item_attribute_base.toItemData4Client());
|
||||
}
|
||||
|
||||
public static async Task onApplyCommonResultOfDeletedItem( this TransactionRunner transactionRunner
|
||||
, ItemBase deletedItemInBag )
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var owner = transactionRunner.getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(deletedItemInBag, () => $"deletedItemInBag is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var item_attribute_base = deletedItemInBag.getEntityAttribute<ItemAttributeBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {owner.toBasicString()}");
|
||||
|
||||
(var result, var entity_common_result) = transactionRunner.getOrNewEntityCommonResult(item_attribute_base);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().fatal(result.toBasicString());
|
||||
|
||||
// 유저 로그 아웃 처리 필요 !!!
|
||||
return;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(entity_common_result, () => $"entity_common_result is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var item_result = entity_common_result.Item;
|
||||
NullReferenceCheckHelper.throwIfNull(item_result, () => $"item_result is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var item_guid = item_attribute_base.ItemGuid;
|
||||
item_result.DeletedItems.Add(item_guid);
|
||||
}
|
||||
}
|
||||
48
ServerCommon/Helper/TypeHelper.cs
Normal file
48
ServerCommon/Helper/TypeHelper.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using ServerCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class TypeHelper
|
||||
{
|
||||
public static EPlaceType toPlaceType(this ContentsType contentsType)
|
||||
{
|
||||
switch (contentsType)
|
||||
{
|
||||
case ContentsType.None:
|
||||
return EPlaceType.NONE;
|
||||
case ContentsType.MyHome:
|
||||
return EPlaceType.MyHome;
|
||||
case ContentsType.DressRoom:
|
||||
return EPlaceType.DressRoom;
|
||||
case ContentsType.Concert:
|
||||
return EPlaceType.Concert;
|
||||
case ContentsType.Movie:
|
||||
return EPlaceType.Movie;
|
||||
case ContentsType.Instance:
|
||||
return EPlaceType.Instance;
|
||||
case ContentsType.BeaconCreateRoom:
|
||||
return EPlaceType.BeaconCreateRoom;
|
||||
case ContentsType.BeaconEditRoom:
|
||||
return EPlaceType.BeaconEditRoom;
|
||||
case ContentsType.BeaconDraftRoom:
|
||||
return EPlaceType.BeaconDraftRoom;
|
||||
case ContentsType.EditRoom:
|
||||
return EPlaceType.EditRoom;
|
||||
case ContentsType.BeaconCustomizeRoom:
|
||||
return EPlaceType.BeaconCustomizeRoom;
|
||||
case ContentsType.BattleRoom:
|
||||
return EPlaceType.BattleRoom;
|
||||
case ContentsType.ArcadeRunning:
|
||||
return EPlaceType.ArcadeRunning;
|
||||
}
|
||||
|
||||
return EPlaceType.NONE;
|
||||
}
|
||||
}
|
||||
34
ServerCommon/Helper/UserBlockHelper.cs
Normal file
34
ServerCommon/Helper/UserBlockHelper.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Amazon.DynamoDBv2.DataModel;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public class UserBlockHelper
|
||||
{
|
||||
public static HashSet<string> convertBlockPolicyToJavaPolicy(List<string> blockPolicy)
|
||||
{
|
||||
HashSet<string> policies = new();
|
||||
foreach (var policy in blockPolicy)
|
||||
{
|
||||
switch (policy)
|
||||
{
|
||||
case "Access_Restrictions":
|
||||
policies.Add(UserBlockPolicyType.AccessRestrictions.ToString());
|
||||
break;
|
||||
case "Chatting_Restrictions":
|
||||
policies.Add(UserBlockPolicyType.ChattingRestrictions.ToString());
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.getLogger($"BlockPolicy not match policy : {policy}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return policies;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user