초기커밋
This commit is contained in:
55
GameServer/0. Base/BaseGetSet.cs
Normal file
55
GameServer/0. Base/BaseGetSet.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
|
||||
public partial class GameServerLogic : ServerLogicBase, IWithPacketNamespaceVerifier, IWithServerMetrics
|
||||
{
|
||||
public Map getMap() => m_map;
|
||||
public PlayerManager getPlayerManager() => m_player_manager;
|
||||
public SystemMetaMailManager getSystemMailManager() => m_system_mail_manager;
|
||||
public UgqApiManager GetUqgApiManager() => m_ugq_api_manager;
|
||||
public ChannelManager getChannelManager() => m_channel_manager;
|
||||
public NoticeChatManager getNoticeChatManager() => m_notice_chat_manager;
|
||||
public SeasonPassManager getSeasonPassManager() => m_season_pass_manager;
|
||||
public LandManager getLandManager() => m_land_manager;
|
||||
public BuildingManager getBuildingManager() => m_building_manager;
|
||||
|
||||
public ReservationManager getReservationManager()
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(m_reservation_manager, () => $"ReservationManager is null");
|
||||
return m_reservation_manager;
|
||||
}
|
||||
public ReturnManager getReturnManager()
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(m_return_manager, () => $"ReturnManager is null");
|
||||
return m_return_manager;
|
||||
}
|
||||
|
||||
|
||||
public ServerMetricsCacheRequest getServerMetricsCacheRequest()
|
||||
{
|
||||
return ServerBase.ServerMetricsHelper.getServerMetricsCacheRequest(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public partial class GameLoginListener : ProudNetListener
|
||||
{
|
||||
public GameServerLogic getGameServerLogic()
|
||||
{
|
||||
var game_server_logic = getServerLogicBase() as GameServerLogic;
|
||||
NullReferenceCheckHelper.throwIfNull(game_server_logic, () => $"game_server_logic is null !!!");
|
||||
return game_server_logic;
|
||||
}
|
||||
}
|
||||
16
GameServer/1. Define/Constant.cs
Normal file
16
GameServer/1. Define/Constant.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
|
||||
//public static class Constant
|
||||
//{
|
||||
|
||||
|
||||
//}
|
||||
563
GameServer/Contents/AIChat/Action/AIChatAction.cs
Normal file
563
GameServer/Contents/AIChat/Action/AIChatAction.cs
Normal file
@@ -0,0 +1,563 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
using static ServerCommon.MetaHelper;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
using Amazon.S3.Model;
|
||||
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class AIChatAction : EntityActionBase
|
||||
{
|
||||
private string user_jwt = string.Empty;
|
||||
|
||||
public AIChatAction(Player owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
user_jwt = string.Empty;
|
||||
}
|
||||
|
||||
//-------------인증 JWT 관련 API-------------
|
||||
//특정 유저의 JWT를 검증합니다.
|
||||
public async Task<(Result, AIChatJwtInfo?)> jwtverify(string user_jwt)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
if (server_logic.getServerConfig().OfflineMode == true)
|
||||
{
|
||||
result.setFail(ServerErrorCode.AiChatServerInactive);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var url = $"/api/auth/jwt/verify";
|
||||
(result, string resMsg) = await AIChatServerConnector.sendAIChatServer("GET", url, user_jwt, null);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed ai chat server action : jwtverify, msg : {resMsg}");
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatJwtVerify);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
try
|
||||
{
|
||||
var aichat_jwt_info = JsonConvert.DeserializeObject<AIChatJwtInfo>(resMsg);
|
||||
return (result, aichat_jwt_info);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
//특정 유저의 JWT를 발행합니다.
|
||||
public async Task<(Result, string?)> jwtIssue(string user_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
if (server_logic.getServerConfig().OfflineMode == true)
|
||||
{
|
||||
result.setFail(ServerErrorCode.AiChatServerInactive);
|
||||
return (result, string.Empty);
|
||||
}
|
||||
|
||||
var url = $"/api/auth/jwt/issue/{user_guid}";
|
||||
var body = AIChatServerConnector.getUserJwtJson();
|
||||
|
||||
(result, string resMsg) = await AIChatServerConnector.sendAIChatServer("POST", url, null, body);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed ai chat server action : jwtIssue, msg : {resMsg}");
|
||||
return (result, string.Empty);
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatJwtIssue);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
try
|
||||
{
|
||||
var ai_chat_issue_jwt = JsonConvert.DeserializeObject<AIChatIssueJwt>(resMsg);
|
||||
NullReferenceCheckHelper.throwIfNull(ai_chat_issue_jwt, () => $"ai_chat_issue_jwt is null !!! - {toBasicString()}");
|
||||
|
||||
user_jwt = ai_chat_issue_jwt.jwt == null ? string.Empty : ai_chat_issue_jwt.jwt;
|
||||
|
||||
return (result, user_jwt);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
//포인트 충전
|
||||
public async Task<Result> pointCharge(AIChatPointCharge aIChatPointCharge)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/point/charge";
|
||||
var body = JsonConvert.SerializeObject(aIChatPointCharge);
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("PUT", url, body);
|
||||
if (result.isFail())
|
||||
{
|
||||
if (result.ErrorCode == ServerErrorCode.AiChatServerInactive)
|
||||
return result;
|
||||
|
||||
result.setFail(ServerErrorCode.AiChatServerRetryChargePoint);
|
||||
Log.getLogger().error($"Failed ai chat server action : pointCharge, msg : {resMsg}");
|
||||
return result;
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatPointCharge);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
//포인트 충전 확인
|
||||
public async Task<Result> pointChargeCheckByOrderGuid(string order_guid)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var aIPointVerify = new AIChatPointVerify() { orderGuid = order_guid };
|
||||
|
||||
var url = $"/api/point/charge";
|
||||
var body = JsonConvert.SerializeObject(aIPointVerify);
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, body);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatPointChargeVerify);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
//어제까지의 벌어들인 미청구 포인트 조회
|
||||
public async Task<(Result, AIChatPointClaimables?)> pointClaimables(int page, int num_per_page, string user_guid)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/point/claimables/{user_guid}?page={page}&numPerPage={num_per_page}";
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, null);
|
||||
if (result.isFail())
|
||||
{
|
||||
if (result.ErrorCode == ServerErrorCode.AiChatServerUserNotFound)
|
||||
{
|
||||
result = await registerUser(player.getUserGuid(), player.getUserNickname());
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
(result, resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, null);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatIncentiveSearch);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
try
|
||||
{
|
||||
var aichat_point_claim_ables = JsonConvert.DeserializeObject<AIChatPointClaimables>(resMsg);
|
||||
return (result, aichat_point_claim_ables);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
//인센티브 수령 완료 표시
|
||||
public async Task<Result> pointMarkClaimed(string user_guid, int marking_day)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"server_logic is null !!!");
|
||||
|
||||
var url = $"/api/point/mark-as-claimed/{user_guid}?aggregationEndTime={marking_day}";
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("POST", url, null);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed ai chat server action : pointMarkClaimed, msg : {resMsg}");
|
||||
return result;
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatIncentiveMarking);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
//신규 유저 등록
|
||||
public async Task<Result> registerUser(string user_guid, string name)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/user/{user_guid}";
|
||||
|
||||
var aIRegisterUser = new AIChatRegisterUser() { nick = name };
|
||||
var body = JsonConvert.SerializeObject(aIRegisterUser);
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("POST", url, body);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed ai chat server action : registerUser, user_guid : {user_guid}, name : {name}, msg : {resMsg}");
|
||||
return result;
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatRegisterUser);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
//유저 등록 제거
|
||||
public async Task<Result> deleteUser(string user_guid)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/user/{user_guid}";
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("DELETE", url, null);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatDeleteUser);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
//특정 캐릭터 조회
|
||||
public async Task<(Result, AIChatCharacter?)> getCharacterByTargetGuid(string target_guid)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/character/{target_guid}";
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, null);
|
||||
if (result.isFail()) return (result, null);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatGetCharacter);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
try
|
||||
{
|
||||
var aichat_character = JsonConvert.DeserializeObject<AIChatCharacter>(resMsg);
|
||||
return (result, aichat_character);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------유저 권한 API-------------
|
||||
//신규 캐릭터 등록
|
||||
public async Task<Result> registerCharacter(AIChatRegisterCharacter aIChatRegisterCharacter)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/character";
|
||||
var body = JsonConvert.SerializeObject(aIChatRegisterCharacter);
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("POST", url, body);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed ai chat server action : registerCharacter, msg : {resMsg}");
|
||||
return result;
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatRegisterCharacter);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
//캐릭터 수정
|
||||
public async Task<Result> updateCharacter(AIChatRegisterCharacter aIChatRegisterCharacter)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/character/locale/{aIChatRegisterCharacter.guid}";
|
||||
var body = JsonConvert.SerializeObject(aIChatRegisterCharacter);
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("PUT", url, body);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatUpdateCharacter);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
//캐릭터 등록 제거
|
||||
public async Task<Result> deleteCharacter(string character_guid)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var url = $"/api/character/{character_guid}";
|
||||
|
||||
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("DELETE", url, null);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.AIChatDeleteCharacter);
|
||||
|
||||
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
|
||||
invokers.Add(new AIChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 데이터 수집 기간 : 월요일 00:00:00 ~ 일요일 23:59:59(KST 기준 - UTC+9)
|
||||
/// 인센티브 보상 지급 날짜 및 시각 : 매주 월요일 05:00 (KST 기준 - UTC+9)
|
||||
/// </summary>
|
||||
|
||||
public async Task<Result> updateTickOfIncentivePoint()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var current_time = DateTimeHelper.Current;
|
||||
var incentive_collect_time = current_time.AddDays(Convert.ToInt32(DayOfWeek.Monday) - Convert.ToInt32(current_time.DayOfWeek)).Date;
|
||||
var incentive_provide_time = incentive_collect_time.AddHours(5);
|
||||
|
||||
var ai_chat_attribute = player.getEntityAttribute<AiChatAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ai_chat_attribute, () => $"ai_chat_attribute is null !!! - {player.toBasicString()}");
|
||||
var last_incentive_provide_time = ai_chat_attribute.LastIncentiveProvideTime;
|
||||
|
||||
if (last_incentive_provide_time != default ||
|
||||
last_incentive_provide_time == incentive_provide_time ||
|
||||
incentive_provide_time > current_time)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await TakeIncentivePoint(incentive_provide_time);
|
||||
if(result.isFail()) return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> TakeIncentivePoint(DateTime new_incentive_provide_time)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
|
||||
var mail_action = player.getEntityAction<MailAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(mail_action, () => $"mail_action is null !!!");
|
||||
|
||||
var ai_chat_attribute = player.getEntityAttribute<AiChatAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ai_chat_attribute, () => $"ai_chat_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
if (MetaData.Instance._CurrencyMetaTableByCurrencyType.TryGetValue(CurrencyType.Beam, out var currencyMetaData) == false)
|
||||
{
|
||||
result.setFail(ServerErrorCode.CurrencyNotFoundData, err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, var pointClaim) = await pointClaimables(0, 100, player.getUserGuid());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(pointClaim, () => $"pointClaim is null !!! - {toBasicString()}");
|
||||
if (pointClaim.items.Count == 0)
|
||||
{
|
||||
ai_chat_attribute.LastIncentiveProvideTime = new_incentive_provide_time;
|
||||
ai_chat_attribute.modifiedEntityAttribute();
|
||||
|
||||
(result, var ai_chat_doc) = await ai_chat_attribute.toDocBase();
|
||||
if (result.isFail()) return result;
|
||||
NullReferenceCheckHelper.throwIfNull(ai_chat_doc, () => $"ai_chat_doc is null !!! - {player.toBasicString()}");
|
||||
|
||||
result = await dynamo_db_client.simpleUpdateDocumentWithDocType(ai_chat_doc);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to simpleUpdateDocumentWithDocType ai_chat_doc !!! - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
var IncentivePointList = new List<int>();
|
||||
int maxPoint = GameConfigMeta.AiChatInsentiveMax;
|
||||
int last_incentive_period = 0;
|
||||
|
||||
foreach (var pointInfo in pointClaim.items)
|
||||
{
|
||||
int amount = pointInfo.amount;
|
||||
if(maxPoint < amount)
|
||||
{
|
||||
amount = maxPoint;
|
||||
}
|
||||
|
||||
IncentivePointList.Add(amount);
|
||||
if(last_incentive_period < pointInfo.end_time)
|
||||
{
|
||||
last_incentive_period = pointInfo.end_time;
|
||||
}
|
||||
}
|
||||
|
||||
var fn_send_system_mail = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var receivedMailDocs = new List<DynamoDbDocBase>();
|
||||
foreach (var amount in IncentivePointList)
|
||||
{
|
||||
var mail_items = new List<ServerCommon.MailItem>() { new ServerCommon.MailItem() { ItemId = (META_ID)currencyMetaData.ItemId, Count = amount } };
|
||||
(result, var receivedMailDoc) = await mail_action.tryMakeNewSystemMail(mail_items, ServerCommon.Constant.NPC_INSENTIVE_META_KEY, GameConfigMeta.AiChatInsentivePeriod, string.Empty);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(receivedMailDoc, () => $"receivedMailDoc is null !!! - {toBasicString()}");
|
||||
receivedMailDocs.Add(receivedMailDoc);
|
||||
}
|
||||
|
||||
ai_chat_attribute.LastIncentiveProvideTime = new_incentive_provide_time;
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.MailAiChatIncentivePoint
|
||||
, dynamo_db_client);
|
||||
{
|
||||
batch.addQuery(new DBQEntityWrite(receivedMailDocs));
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await pointMarkClaimed(player.getUserGuid(), last_incentive_period);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
mail_action.NewReceivedMail();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var transaction_name = "provideIncentivePoint";
|
||||
result = await player.runTransactionRunnerSafelyWithTransGuid(player.getUserGuid()
|
||||
, TransactionIdType.PrivateContents, transaction_name
|
||||
, fn_send_system_mail);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafelyWithTransGuid() !!! : {result.toBasicString()} - transactionName:{transaction_name}, {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
216
GameServer/Contents/AIChat/Action/AIChatSchema.cs
Normal file
216
GameServer/Contents/AIChat/Action/AIChatSchema.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class AIChatJwt
|
||||
{
|
||||
public string messageBase64 { get; set; } = string.Empty;
|
||||
public string signatureBase64 { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class AIChatPointVerify
|
||||
{
|
||||
public string orderGuid { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class AIChatError
|
||||
{
|
||||
public int code { get; set; } = 0;
|
||||
public string name { get; set; } = string.Empty;
|
||||
public string message { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class AIChatJwtInfo
|
||||
{
|
||||
public string guid { get; set; } = string.Empty;
|
||||
public string role { get; set; } = string.Empty;
|
||||
public int iat { get; set; } = 0;
|
||||
public int exp { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatRegisterCharacter
|
||||
{
|
||||
public string guid { get; set; } = string.Empty;
|
||||
public string ownerUserGuid { get; set; } = string.Empty;
|
||||
public string lang { get; set; } = string.Empty;
|
||||
public string name { get; set; } = string.Empty;
|
||||
public string persona { get; set; } = string.Empty;
|
||||
public string firstMes { get; set; } = string.Empty;
|
||||
public string secrets { get; set; } = string.Empty; // Not Used
|
||||
public string shortDesc { get; set; } = string.Empty;
|
||||
|
||||
public List<META_ID> tags { get; set; } = new();
|
||||
public bool isOfficial { get; set; } = false;
|
||||
|
||||
public List<AIChatSocialActionConfig> socialActionConfig = new();
|
||||
|
||||
public AIChatCharacterAttribute attributes { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AIChatCharacterAttribute
|
||||
{
|
||||
public int gender { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatIssueJwt
|
||||
{
|
||||
public string jwt { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class AIChatSocialActionConfig
|
||||
{
|
||||
public int id { get; set; } = 0;
|
||||
public float weight { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatPointClaimables
|
||||
{
|
||||
public int page { get; set; } = 0;
|
||||
public int numPerPage { get; set; } = 0;
|
||||
public int total { get; set; } = 0;
|
||||
public List<AIChatPointClaimablesItems> items { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AIChatPointClaimablesItems
|
||||
{
|
||||
public int start_time { get; set; } = 0;
|
||||
public int end_time { get; set; } = 0;
|
||||
public int amount { get; set; } = 0;
|
||||
public int log_count { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatPointHistory
|
||||
{
|
||||
public int page { get; set; } = 0;
|
||||
public int numPerPage { get; set; } = 0;
|
||||
public int total { get; set; } = 0;
|
||||
public List<AIChatPointHistoryItems> items { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AIChatPointHistoryItems
|
||||
{
|
||||
public string created_date { get; set; } = string.Empty;
|
||||
public int sum_of_spend_free { get; set; } = 0;
|
||||
public int sum_of_earn_free { get; set; } = 0;
|
||||
public int sum_of_charge_free { get; set; } = 0;
|
||||
public int sum_of_spend_nonfree { get; set; } = 0;
|
||||
public int sum_of_earn_nonfree { get; set; } = 0;
|
||||
public int sum_of_charge_nonfree { get; set; } = 0;
|
||||
public int free_points_balance { get; set; } = 0;
|
||||
public int nonfree_points_balance { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatPointCharge
|
||||
{
|
||||
public double points { get; set; } = 0;
|
||||
public string pointType { get; set; } = string.Empty;
|
||||
public string userGuid { get; set; } = string.Empty;
|
||||
public string orderGuid { get; set; } = string.Empty;
|
||||
public string description { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class AIChatSetting
|
||||
{
|
||||
public string id { get; set; } = string.Empty;
|
||||
public string model { get; set; } = string.Empty;
|
||||
public AIChatPoint point { get; set; } = new AIChatPoint();
|
||||
public bool enabled { get; set; } = false;
|
||||
public int token_limit { get; set; } = 0;
|
||||
public AIChatOptions options { get; set; } = new AIChatOptions();
|
||||
}
|
||||
|
||||
public class AIChatPoint
|
||||
{
|
||||
public int cost { get; set; } = 0;
|
||||
public int share { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatOptions
|
||||
{
|
||||
public float temperature { get; set; } = 0;
|
||||
public float top_p { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatRegisterUser
|
||||
{
|
||||
public string nick { get; set; } = string.Empty;
|
||||
public AIChatRegisterUserSetting settings { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AIChatRegisterUserSetting
|
||||
{
|
||||
public string defaultModel { get; set; } = ServerCommon.Constant.AI_CHAT_DEFAULT_MODEL;
|
||||
}
|
||||
|
||||
public class AIChatRanking
|
||||
{
|
||||
public List<AIChatRankingData> items { get; set; } = new();
|
||||
public int page { get; set; } = 0;
|
||||
public int numPerPage { get; set; } = 0;
|
||||
public int total { get; set; } = 0;
|
||||
public int start_at { get; set; } = 0;
|
||||
public int end_at { get; set; } = 0;
|
||||
}
|
||||
public class AIChatRankingData
|
||||
{
|
||||
public string char_guid { get; set; } = string.Empty;
|
||||
public string owner_guid { get; set; } = string.Empty;
|
||||
public string owner_nick { get; set; } = string.Empty;
|
||||
public string char_name { get; set; } = string.Empty;
|
||||
public int total_chat_count { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class AIChatCharacter
|
||||
{
|
||||
public string itemId { get; set; } = string.Empty;
|
||||
public AIChatCharacterInfo data { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AIChatCharacterInfo
|
||||
{
|
||||
public string guid { get; set; } = string.Empty;
|
||||
public string owner_guid { get; set; } = string.Empty;
|
||||
public Int64 chat_count { get; set; } = 0;
|
||||
|
||||
public List<AIChatSocialActionConfig> socialActionConfig = new();
|
||||
|
||||
public string created_at { get; set; } = string.Empty;
|
||||
public string updated_at { get; set; } = string.Empty;
|
||||
public bool is_official { get; set; } = false;
|
||||
|
||||
public AiChatCharacterLocales locale { get; set; } = new();
|
||||
|
||||
public List<META_ID> tags { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AiChatCharacterLocales
|
||||
{
|
||||
AiChatCharacterLocale en = new();
|
||||
AiChatCharacterLocale ko = new();
|
||||
AiChatCharacterLocale ja = new();
|
||||
}
|
||||
|
||||
public class AiChatCharacterLocale
|
||||
{
|
||||
public string id { get; set; } = string.Empty;
|
||||
public string lang { get; set; } = string.Empty;
|
||||
public string name { get; set; } = string.Empty;
|
||||
public string persona { get; set; } = string.Empty;
|
||||
public string first_mes { get; set; } = string.Empty;
|
||||
public string secrets { get; set; } = string.Empty;
|
||||
public string short_desc { get; set; } = string.Empty;
|
||||
public string created_at { get; set; } = string.Empty;
|
||||
public string updated_at { get; set; } = string.Empty;
|
||||
}
|
||||
32
GameServer/Contents/AIChat/Log/AIChatBusinessLog.cs
Normal file
32
GameServer/Contents/AIChat/Log/AIChatBusinessLog.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class AIChatBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private AIChatLogData m_data_to_log;
|
||||
public AIChatBusinessLog(AIChatLogData log_data_param)
|
||||
: base(LogDomainType.AIChat)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new AIChatLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
25
GameServer/Contents/AIChat/Log/AIChatBusinessLogHelper.cs
Normal file
25
GameServer/Contents/AIChat/Log/AIChatBusinessLogHelper.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
static public class AIChatBusinessLogHelper
|
||||
{
|
||||
static public AIChatLogData toLogInfo(string URL, string bodyParamJson)
|
||||
{
|
||||
var logData = new AIChatLogData();
|
||||
logData.setInfo(URL, bodyParamJson);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this AIChatLogData logData, string URL, string bodyParamJson)
|
||||
{
|
||||
logData.AIChatURL = URL;
|
||||
logData.AIChatBodyParamJson = bodyParamJson;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler
|
||||
{
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_AICHAT_AUTH), typeof(AIChatAuthPacketHandler), typeof(GameLoginListener))]
|
||||
public class AIChatAuthPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_AICHAT_AUTH(Player player, Result result, string? jwt = null, int leftTime = 0)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckAIChatAuth = new GS2C_ACK_AICHAT_AUTH();
|
||||
ack_packet.Response.AckAIChatAuth.Jwt = jwt ?? string.Empty;
|
||||
ack_packet.Response.AckAIChatAuth.LeftTime = leftTime;
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var ai_chat_action = player.getEntityAction<AIChatAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ai_chat_action, () => $"ai_chat_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, var jwt) = await ai_chat_action.jwtIssue(player.getUserGuid());
|
||||
if(result.ErrorCode == ServerErrorCode.AiChatServerUserNotFound)
|
||||
{
|
||||
result = await ai_chat_action.registerUser(player.getUserGuid(), player.getUserNickname());
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed Register User : {player.getUserGuid()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
send_S2C_ACK_AICHAT_AUTH(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, jwt) = await ai_chat_action.jwtIssue(player.getUserGuid());
|
||||
}
|
||||
|
||||
if(result.isFail() || string.IsNullOrEmpty(jwt))
|
||||
{
|
||||
send_S2C_ACK_AICHAT_AUTH(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
(result, var jwtInfo) = await ai_chat_action.jwtverify(jwt);
|
||||
if (result.isFail() || jwt == null)
|
||||
{
|
||||
send_S2C_ACK_AICHAT_AUTH(player, result);
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(jwtInfo, () => $"jwtInfo is null !!");
|
||||
|
||||
send_S2C_ACK_AICHAT_AUTH(player, result, jwt, jwtInfo.exp - jwtInfo.iat);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_AICHAT_AUTH(player, errorResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Text.Json.Nodes;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Amazon.Runtime.Internal.Endpoints.StandardLibrary;
|
||||
using Amazon.Runtime.Internal.Transform;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Signers;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
using static ServerCommon.MetaHelper;
|
||||
using static ServerCommon.BusinessLogDomain.MailLogData;
|
||||
|
||||
|
||||
using GameServer.PacketHandler;
|
||||
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class AdvertisementAction : EntityActionBase
|
||||
{
|
||||
public AdvertisementAction(Player owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public async Task<(Result, int)> selectAdvertisement(int interiorId)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
if (MetaData.Instance._InteriorMetaTable.TryGetValue(interiorId, out var interiorMeta) == false)
|
||||
{
|
||||
result.setFail(ServerErrorCode.InteriorMetaDataNotFound, err_msg);
|
||||
return (result, -1);
|
||||
}
|
||||
|
||||
int index = Random.Shared.Next(interiorMeta.AdPath.Count);
|
||||
|
||||
|
||||
return (result, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_SELECT_ADVERTISEMENT), typeof(AdvertisementPacketHandler), typeof(GameLoginListener))]
|
||||
public class AdvertisementPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_GS2C_ACK_SELECT_ADVERTISEMENT(Player player, Result result, int index)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckSelectAdvertisement = new GS2C_ACK_SELECT_ADVERTISEMENT();
|
||||
ack_packet.Response.AckSelectAdvertisement.Index = index;
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var request = (recvMessage as ClientToGame)?.Request.ReqSelectAdvertisement;
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!!");
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var advertisement_action = player.getEntityAction<AdvertisementAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(advertisement_action, () => $"ai_chat_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, int index) = await advertisement_action.selectAdvertisement(request.InteriorId);
|
||||
send_GS2C_ACK_SELECT_ADVERTISEMENT(player, result, index);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class BeaconAppearanceCustomizeAction : EntityActionBase
|
||||
{
|
||||
public BeaconAppearanceCustomizeAction(UgcNpc owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public async Task<Result> tryLoadAppearanceCustomizeFromDoc(AppearanceCustomizeDoc appearanceCustomizeDoc)
|
||||
{
|
||||
var beacon = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(beacon, () => $"beacon is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(appearanceCustomizeDoc, () => $"appearanceCustomizeDoc is null !!! - {beacon.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var appearance_customize_attrib = appearanceCustomizeDoc.getAttrib<AppearanceCustomizeAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_customize_attrib, () => $"appearance_customize_attrib is null !!! - {beacon.toBasicString()}");
|
||||
|
||||
var appearance_customize_attribute = beacon.getEntityAttribute<AppearanceCustomizeAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_customize_attribute, () => $"appearance_customize_attribute is null !!!");
|
||||
|
||||
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromDocs(appearance_customize_attribute, new List<DynamoDbDocBase>() { appearanceCustomizeDoc });
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromDocs() !!!, to:{appearance_customize_attribute.getTypeName()}, from:{appearanceCustomizeDoc.getTypeName()} : {result.toBasicString()} - {beacon.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> tryCustomizeAppearance(AppearanceCustomization appearCustomize)
|
||||
{
|
||||
var beacon = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(beacon, () => $"beacon is null !!!");
|
||||
|
||||
var player = beacon.onGetMasterEntity();
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(appearCustomize, () => $"appearCustomize is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ugcn_npc_action = beacon.getEntityAction<UgcNpcAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugcn_npc_action, () => $"ugcn_npc_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
//=====================================================================================
|
||||
// 1. 비컨의 배치 상태를 체크 한다.
|
||||
//=====================================================================================
|
||||
if (true == ugcn_npc_action.isLocatedUgcNpc())
|
||||
{
|
||||
err_msg = $"UgcNpc located state !!! : {beacon.toSummaryString()} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcLocatedState, err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 2. 금전을 소모 한다.
|
||||
//=====================================================================================
|
||||
var money_action = player.getEntityAction<MoneyAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var req_currency_type = (CurrencyType)ServerCommon.MetaHelper.GameConfigMeta.NpcCustomizeCostType;
|
||||
result = await money_action.spendMoney(req_currency_type, ServerCommon.MetaHelper.GameConfigMeta.NpcCustomizeCost);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 3. 비컨 외형 커스마이징 정보를 갱신 한다.
|
||||
//=====================================================================================
|
||||
updateAppearanceCustomize(appearCustomize);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void updateAppearanceCustomize(AppearanceCustomization appearCustomize)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(appearCustomize, () => $"appearCustomize is null !!!");
|
||||
|
||||
var beacon = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(beacon, () => $"beacon is null !!!");
|
||||
|
||||
var player = beacon.onGetMasterEntity();
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var appearance_customize_attribute = beacon.getEntityAttribute<AppearanceCustomizeAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_customize_attribute, () => $"appearance_customize_attribute is null !!!");
|
||||
|
||||
appearance_customize_attribute.BasicStyle = appearCustomize.BasicStyle;
|
||||
appearance_customize_attribute.BodyShape = appearCustomize.BodyShape;
|
||||
appearance_customize_attribute.HairStyle = appearCustomize.HairStyle;
|
||||
appearance_customize_attribute.CustomValues = appearCustomize.CustomValues.ToList();
|
||||
|
||||
appearance_customize_attribute.modifiedEntityAttribute(true);
|
||||
}
|
||||
|
||||
public AppearanceCustomization toAppearanceCustomization()
|
||||
{
|
||||
var beacon = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(beacon, () => $"beacon is null !!!");
|
||||
|
||||
var appearance_customize_attribute = beacon.getEntityAttribute<AppearanceCustomizeAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_customize_attribute, () => $"appearance_customize_attribute is null !!!");
|
||||
|
||||
var appearance_customize = new AppearanceCustomization();
|
||||
|
||||
appearance_customize.BasicStyle = appearance_customize_attribute.BasicStyle;
|
||||
appearance_customize.BodyShape = appearance_customize_attribute.BodyShape;
|
||||
appearance_customize.HairStyle = appearance_customize_attribute.HairStyle;
|
||||
appearance_customize.CustomValues.AddRange(appearance_customize_attribute.CustomValues.ToList());
|
||||
|
||||
return appearance_customize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using static StackExchange.Redis.Role;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using static ServerCommon.MetaHelper;
|
||||
|
||||
|
||||
using GameServer;
|
||||
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class CharacterAppearanceCustomizeAction : EntityActionBase
|
||||
{
|
||||
public CharacterAppearanceCustomizeAction(Character owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public async Task<(Result, CharacterAttribute.AppearanceProfile?)> tryCustomizeAppearance(AppearanceCustomization appearCustomize)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(appearCustomize, () => $"appearCustomize is null !!!");
|
||||
|
||||
var character = getOwner() as Character;
|
||||
NullReferenceCheckHelper.throwIfNull(character, () => $"character is null !!!");
|
||||
|
||||
var player = character.getRootParent() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
//=====================================================================================
|
||||
// 1. 금전을 소모 한다.
|
||||
//=====================================================================================
|
||||
var money_action = player.getEntityAction<MoneyAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var req_currency_type = (CurrencyType)ServerCommon.MetaHelper.GameConfigMeta.CharacterCustomizeCostType;
|
||||
result = await money_action.spendMoney(req_currency_type, GameConfigMeta.CharacterCustomizeCost);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 2. 캐릭터 외형 커스마이징 정보를 갱신 한다.
|
||||
//=====================================================================================
|
||||
var appearance_profile = updateAppearanceCustomize(appearCustomize);
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_profile, () => $"appearance_profile is null !!! - {player.toBasicString()}");
|
||||
|
||||
return (result, appearance_profile);
|
||||
}
|
||||
|
||||
private CharacterAttribute.AppearanceProfile updateAppearanceCustomize(AppearanceCustomization appearCustomize)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(appearCustomize, () => $"appearCustomize is null !!!");
|
||||
|
||||
var character = getOwner() as Character;
|
||||
NullReferenceCheckHelper.throwIfNull(character, () => $"character is null !!!");
|
||||
|
||||
var character_attribute = character.getEntityAttribute<CharacterAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(character_attribute, () => $"character_attribute is null !!!");
|
||||
|
||||
var appearance_profile = character_attribute.AppearanceProfileValue;
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_profile, () => $"appearance_profile is null !!!");
|
||||
|
||||
|
||||
appearance_profile.BasicStyle = (UInt32)appearCustomize.BasicStyle;
|
||||
appearance_profile.BodyShape = (UInt32)appearCustomize.BodyShape;
|
||||
appearance_profile.HairStyle = (UInt32)appearCustomize.HairStyle;
|
||||
appearance_profile.CustomValues = appearCustomize.CustomValues.ToList();
|
||||
|
||||
character_attribute.modifiedEntityAttribute();
|
||||
|
||||
return appearance_profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
|
||||
using Amazon.S3.Model;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
|
||||
[ChatCommandAttribute("charappearcustom", typeof(ChatCharacterCustomize), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
public class ChatCharacterCustomize : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"Call charappearcustom !!! - {player.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (args.Length < 3)
|
||||
{
|
||||
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 1 - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
var read_params = new List<int>();
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
var param = args[i];
|
||||
if (true == param.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Arg {i} is Empty !!! - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (false == int.TryParse(param, out var value))
|
||||
{
|
||||
err_msg = $"Failed to TryParse() !!! - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
read_params.Add(value);
|
||||
}
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!!");
|
||||
|
||||
var selected_character = player_action.getSelectedCharacter();
|
||||
NullReferenceCheckHelper.throwIfNull(selected_character, () => $"selected_character is null !!!");
|
||||
|
||||
var character_attribute = selected_character.getEntityAttribute<CharacterAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(character_attribute, () => $"character_attribute is null !!!");
|
||||
|
||||
var to_change_character_guid = character_attribute.CharacterGuid;
|
||||
|
||||
var appearance_customize = new AppearanceCustomization();
|
||||
appearance_customize.BasicStyle = read_params[0];
|
||||
appearance_customize.BodyShape = read_params[1];
|
||||
appearance_customize.HairStyle = read_params[2];
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
||||
|
||||
var session = player as IEntityWithSession;
|
||||
NullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!! - {player.toBasicString()}");
|
||||
|
||||
//=====================================================================================
|
||||
// 패킷 구성
|
||||
//=====================================================================================
|
||||
var packet = new ClientToGame();
|
||||
packet.Request = new ClientToGameReq();
|
||||
var req_msg = new C2GS_REQ_CHARACTER_APPEARANCE_CUSTOMIZE();
|
||||
packet.Request.ReqCharacterAppearanceCustomize = req_msg;
|
||||
|
||||
req_msg.ToChangeCharacterGuid = to_change_character_guid;
|
||||
req_msg.ToApplyAppearCustomize = appearance_customize;
|
||||
|
||||
result = await server_logic.onCallProtocolHandler(session, packet);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onCallProtocolHandler() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[ChatCommandAttribute("beaconappearcustom", typeof(BeaconCharacterCustomize), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
public class BeaconCharacterCustomize : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"Call beaconappearcustom !!! - {player.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (args.Length < 3)
|
||||
{
|
||||
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 1 - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
var read_params = new List<int>();
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
var param = args[i];
|
||||
if (true == param.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Arg {i} is Empty !!! - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (false == int.TryParse(param, out var value))
|
||||
{
|
||||
err_msg = $"Failed to TryParse() !!! - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
read_params.Add(value);
|
||||
}
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!!");
|
||||
|
||||
var had_ugc_npcs = player_action.getHadUgcNpcs().Values.ToList();
|
||||
NullReferenceCheckHelper.throwIfNull(had_ugc_npcs, () => $"had_ugc_npcs is null !!!");
|
||||
|
||||
if(0 >= had_ugc_npcs.Count)
|
||||
{
|
||||
err_msg = $"Had not Beacon !!! : 0 < hadCount:{had_ugc_npcs.Count} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
var selected_seq = RandomHelper.next(0, had_ugc_npcs.Count() - 1);
|
||||
|
||||
var selected_ugc_npc = had_ugc_npcs[selected_seq];
|
||||
|
||||
var beacon_attribute = selected_ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_attribute, () => $"beacon_attribute is null !!!");
|
||||
|
||||
var to_change_beacon_meta_guid = beacon_attribute.UgcNpcMetaGuid;
|
||||
|
||||
var appearance_customize = new AppearanceCustomization();
|
||||
appearance_customize.BasicStyle = read_params[0];
|
||||
appearance_customize.BodyShape = read_params[1];
|
||||
appearance_customize.HairStyle = read_params[2];
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
||||
|
||||
var session = player as IEntityWithSession;
|
||||
NullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!! - {player.toBasicString()}");
|
||||
|
||||
//=====================================================================================
|
||||
// 패킷 구성
|
||||
//=====================================================================================
|
||||
var packet = new ClientToGame();
|
||||
packet.Request = new ClientToGameReq();
|
||||
var req_msg = new C2GS_REQ_BEACON_APPEARANCE_CUSTOMIZE();
|
||||
packet.Request.ReqBeaconAppearanceCustomize = req_msg;
|
||||
|
||||
req_msg.ToChangeUgcNpcMetaGuid = to_change_beacon_meta_guid;
|
||||
req_msg.ToApplyAppearCustomize = appearance_customize;
|
||||
|
||||
result = await server_logic.onCallProtocolHandler(session, packet);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onCallProtocolHandler() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
using BEACON_META_GUID = System.String;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_APPEARANCE_CUSTOMIZE), typeof(BeaconAppearanceCustomizePacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconAppearanceCustomizePacketHandler : PacketRecvHandler
|
||||
{
|
||||
public override async Task onProcessPacketException( ISession entityWithSession, Google.Protobuf.IMessage recvMessage
|
||||
, Result errorResult )
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(entityWithSession);
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
|
||||
var request = recv_msg.Request.ReqBeaconAppearanceCustomize;
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
send_GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE(player, errorResult, request.ToChangeUgcNpcMetaGuid);
|
||||
}
|
||||
|
||||
private static bool send_GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE( Player owner, Result result
|
||||
, BEACON_META_GUID beaconMetaGuid
|
||||
, AppearanceCustomization? appearCustomize = null )
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(result, () => $"result is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
var ack_msg = new GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE();
|
||||
ack_packet.Response.AckBeaconAppearanceCustomize = ack_msg;
|
||||
|
||||
ack_msg.ToChangeUgcNpcMetaGuid = beaconMetaGuid;
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(appearCustomize, () => $"appearCustomize is null !!!");
|
||||
ack_msg.AppearCustomize = appearCustomize;
|
||||
|
||||
var found_transaction_runner = owner.findTransactionRunner(TransactionIdType.PrivateContents);
|
||||
if (null == found_transaction_runner)
|
||||
{
|
||||
err_msg = $"Not found TransactionRunner !!! : {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ack_msg.CommonResult = found_transaction_runner.getCommonResult();
|
||||
}
|
||||
}
|
||||
|
||||
if (false == server_logic.onSendPacket(owner, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, Google.Protobuf.IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
|
||||
|
||||
var request = recv_msg.Request.ReqBeaconAppearanceCustomize;
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
var to_change_beacon_meta_guid = request.ToChangeUgcNpcMetaGuid;
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var selected_character = player_action.getSelectedCharacter();
|
||||
if (null == selected_character)
|
||||
{
|
||||
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE(player, result, to_change_beacon_meta_guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var fn_beacon_appearance_customize = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var found_beacon = player_action.findUgcNpc(to_change_beacon_meta_guid);
|
||||
if(null == found_beacon)
|
||||
{
|
||||
err_msg = $"Not found Beacon !!! : BeaconMetaGuid:{to_change_beacon_meta_guid} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
||||
|
||||
send_GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE(player, result, to_change_beacon_meta_guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
var appearance_customize_action = found_beacon.getEntityAction<BeaconAppearanceCustomizeAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_customize_action, () => $"appearance_customize_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
result = await appearance_customize_action.tryCustomizeAppearance(request.ToApplyAppearCustomize);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to tryCustomizeAppearance() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE(player, result, to_change_beacon_meta_guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.BeaconAppearanceCustomize
|
||||
, server_logic.getDynamoDbClient()
|
||||
, true );
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
batch.addQuery(new QueryFinal());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE(player, result, to_change_beacon_meta_guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
send_GS2C_ACK_BEACON_APPEARANCE_CUSTOMIZE( player, result
|
||||
, to_change_beacon_meta_guid
|
||||
, appearance_customize_action.toAppearanceCustomization());
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "BeaconAppearanceCostomize", fn_beacon_appearance_customize);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
using CHARACTER_GUID = System.String;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_CHARACTER_APPEARANCE_CUSTOMIZE), typeof(CharacterAppearanceCustomizePacketHandler), typeof(GameLoginListener))]
|
||||
public class CharacterAppearanceCustomizePacketHandler : PacketRecvHandler
|
||||
{
|
||||
public override async Task onProcessPacketException( ISession entityWithSession, Google.Protobuf.IMessage recvMessage
|
||||
, Result errorResult )
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(entityWithSession);
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
|
||||
var request = recv_msg.Request.ReqCharacterAppearanceCustomize;
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
send_GS2C_ACK_CHARACTER_APPEARANCE_CUSTOMIZE(player, errorResult, request.ToChangeCharacterGuid);
|
||||
}
|
||||
|
||||
private static bool send_GS2C_ACK_CHARACTER_APPEARANCE_CUSTOMIZE( Player owner, Result result
|
||||
, CHARACTER_GUID characterGuid
|
||||
, AppearanceCustomization? appearCustomize = null)
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(result, () => $"owner is null !!!");
|
||||
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!!");
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
var ack_msg = new GS2C_ACK_CHARACTER_APPEARANCE_CUSTOMIZE();
|
||||
ack_packet.Response.AckCharacterAppearanceCustomize = ack_msg;
|
||||
|
||||
ack_msg.ToChangeCharacterGuid = characterGuid;
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(appearCustomize, () => $"appearCustomize is null !!!");
|
||||
ack_msg.AppearCustomize = appearCustomize;
|
||||
|
||||
var found_transaction_runner = owner.findTransactionRunner(TransactionIdType.PrivateContents);
|
||||
if (null == found_transaction_runner)
|
||||
{
|
||||
err_msg = $"Not found TransactionRunner !!! : {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ack_msg.CommonResult = found_transaction_runner.getCommonResult();
|
||||
}
|
||||
}
|
||||
|
||||
if (false == server_logic.onSendPacket(owner, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, Google.Protobuf.IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
|
||||
|
||||
var request = recv_msg.Request.ReqCharacterAppearanceCustomize;
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
var to_change_character_guid = request.ToChangeCharacterGuid; // 클라이언트는 USER_GUID를 사용 한다.
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var selected_character = player_action.getSelectedCharacter();
|
||||
if (null == selected_character)
|
||||
{
|
||||
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_GS2C_ACK_CHARACTER_APPEARANCE_CUSTOMIZE(player, result, to_change_character_guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!!");
|
||||
|
||||
var fn_character_appearance_customize = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var character_action = selected_character.getEntityAction<CharacterAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(character_action, () => $"character_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var appearance_customize_action = selected_character.getEntityAction<CharacterAppearanceCustomizeAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(appearance_customize_action, () => $"appearance_customize_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, var aprearance_profile) = await appearance_customize_action.tryCustomizeAppearance(request.ToApplyAppearCustomize);
|
||||
NullReferenceCheckHelper.throwIfNull(aprearance_profile, () => $"aprearance_profile is null !!!");
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to tryCustomizeAppearance() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_GS2C_ACK_CHARACTER_APPEARANCE_CUSTOMIZE(player, result, to_change_character_guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.CharacterAppearanceCustomize
|
||||
, server_logic.getDynamoDbClient()
|
||||
, true);
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
batch.addQuery(new QueryFinal());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_GS2C_ACK_CHARACTER_APPEARANCE_CUSTOMIZE(player, result, to_change_character_guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
send_GS2C_ACK_CHARACTER_APPEARANCE_CUSTOMIZE( player, result
|
||||
, to_change_character_guid
|
||||
, aprearance_profile.toCharacterAppearanceCustomize4Client() );
|
||||
|
||||
// 주변 엔티티들에게 통지 한다.
|
||||
character_action.broadcastCharacterInfo();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CharacterAppearanceCostomize", fn_character_appearance_customize);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
1314
GameServer/Contents/BeaconShop/Action/BeaconShopAction.cs
Normal file
1314
GameServer/Contents/BeaconShop/Action/BeaconShopAction.cs
Normal file
File diff suppressed because it is too large
Load Diff
266
GameServer/Contents/BeaconShop/BeaconShopCheat.cs
Normal file
266
GameServer/Contents/BeaconShop/BeaconShopCheat.cs
Normal file
@@ -0,0 +1,266 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System.Net.WebSockets;
|
||||
using static ServerCommon.MetaHelper;
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
[ChatCommandAttribute("beaconshopregisteritem", typeof(CheatBeaconShopregisterItem), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatBeaconShopregisterItem : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatBeaconShopregisterItem");
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Log.getLogger().error($"Invalid Argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (uint.TryParse(args[0], out uint item_meta_id) == false)
|
||||
return;
|
||||
|
||||
var beacon_shop_action = player.getEntityAction<BeaconShopAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_action, () => $"beacon_shop_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var item_list = inventory_action.tryGetItemAllByItemMetaId(item_meta_id);
|
||||
if (item_list.Count == 0)
|
||||
return;
|
||||
|
||||
var item_attribute = item_list[0].getEntityAttribute<ItemAttributeBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
var ugc_npc_dictionary = player_action.getHadUgcNpcs();
|
||||
if (ugc_npc_dictionary.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var npc_attribute = ugc_npc_dictionary.First().Value.getEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(npc_attribute, () => $"npc_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var result = await beacon_shop_action.tryRegisterItemToBeaconShop(item_attribute.ItemGuid, 1, 0.1, npc_attribute.UgcNpcMetaGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("beaconshopreturn", typeof(CheatBeaconShopReturn), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatBeaconShopReturn : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatBeaconShopReturn");
|
||||
|
||||
if (args.Length < 2)
|
||||
{
|
||||
Log.getLogger().error($"Invalid Argument");
|
||||
return;
|
||||
}
|
||||
|
||||
var itemGuid = args[0];
|
||||
var beaconGuid = args[1];
|
||||
|
||||
var beacon_shop_action = player.getEntityAction<BeaconShopAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_action, () => $"beacon_shop_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var result = await beacon_shop_action.BeaconShopReturnItem(itemGuid, beaconGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("beaconshoppurchaseitem", typeof(CheatBeaconShopPurchaseItem), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatBeaconShopPurchaseItem : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatBeaconShopreturn");
|
||||
|
||||
if (args.Length < 4)
|
||||
{
|
||||
Log.getLogger().error($"Invalid Argument");
|
||||
return;
|
||||
}
|
||||
|
||||
var itemGuid = args[0];
|
||||
|
||||
if (ushort.TryParse(args[1], out ushort itemAmount) == false)
|
||||
return;
|
||||
|
||||
var beaconGuid = args[2];
|
||||
var beaconOwnerGuid = args[3];
|
||||
|
||||
var beacon_shop_action = player.getEntityAction<BeaconShopAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_action, () => $"beacon_shop_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var result = await beacon_shop_action.BeaconShopPurchaseItem(itemGuid, itemAmount, beaconGuid, beaconOwnerGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("beaconshopreceivepayment", typeof(CheatBeaconShopReceivePayment), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatBeaconShopReceivePayment : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatBeaconShopReceivePayment");
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Log.getLogger().error($"Invalid Argument");
|
||||
return;
|
||||
}
|
||||
|
||||
var beaconGuid = args[0];
|
||||
|
||||
var beacon_shop_action = player.getEntityAction<BeaconShopAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_action, () => $"beacon_shop_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var result = await beacon_shop_action.BeaconShopReceivePaymentForSales(beaconGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("beaconshopitemtimechange", typeof(CheatBeaconShopItemTimeChange), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatBeaconShopItemTimeChange : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatBeaconShopItemTimeChange");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Log.getLogger().error($"Invalid Argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (int.TryParse(args[0], out int minutes) == false)
|
||||
return;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var fn_start = async delegate ()
|
||||
{
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
|
||||
var npcs = player_action.getHadUgcNpcs();
|
||||
foreach (var npc in npcs)
|
||||
{
|
||||
var ugc_npc_beacon_shop_action = npc.Value.getEntityAction<UgcNpcBeaconShopAction>();
|
||||
var beaconShopItems = ugc_npc_beacon_shop_action.getHasBeaconShopItem();
|
||||
foreach (var beaconShopItem in beaconShopItems)
|
||||
{
|
||||
var beacon_shop_item_attribute = beaconShopItem.getEntityAttribute<BeaconShopItemAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attribute, () => $"beacon_shop_item_attribute is null !!!");
|
||||
|
||||
var cheat_selling_finish_time = DateTime.UtcNow.AddMinutes(minutes);
|
||||
|
||||
beacon_shop_item_attribute.SellingFinishTime = cheat_selling_finish_time;
|
||||
beacon_shop_item_attribute.modifiedEntityAttribute();
|
||||
}
|
||||
}
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CheatCommandBeaconShopItemTimeChange
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
var result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CheatBeaconShopItemTimeChange", fn_start);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("beaconshopdailylimitinit", typeof(CheatBeaconShopDailyLimitInit), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatBeaconShopDailyLimitInit : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatBeaconShopdailylimitinit");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var fn_start = async delegate ()
|
||||
{
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
|
||||
var npcs = player_action.getHadUgcNpcs();
|
||||
foreach (var npc in npcs)
|
||||
{
|
||||
var beacon_shop_profile_attribute = npc.Value.getEntityAttribute<BeaconShopProfileAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_attribute, () => $"beacon_shop_item_attribute is null !!!");
|
||||
|
||||
beacon_shop_profile_attribute.DailyRegisterCount = 0;
|
||||
beacon_shop_profile_attribute.modifiedEntityAttribute();
|
||||
}
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CheatCommandDailyLimitInit
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
var result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CheatBeaconShopdailylimitinit", fn_start);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
140
GameServer/Contents/BeaconShop/BeaconShopItem.cs
Normal file
140
GameServer/Contents/BeaconShop/BeaconShopItem.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using BEACON_GUID = System.String;
|
||||
using USER_GUID = System.String;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class BeaconShopItem : Item
|
||||
{
|
||||
public BeaconShopItem(UgcNpc owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
var direct_parent = getDirectParent();
|
||||
NullReferenceCheckHelper.throwIfNull(direct_parent, () => $"direct_parent is null !!!");
|
||||
addEntityAttribute(new BeaconShopItemAttribute(this, direct_parent));
|
||||
return await base.onInit();
|
||||
}
|
||||
|
||||
public override string toBasicString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public override string toSummaryString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public static async Task<(Result, BeaconShopItem?)> createBeaconShopFromDoc(UgcNpc owner, BeaconShopItemDoc doc)
|
||||
{
|
||||
var beacon_shop_item = new BeaconShopItem(owner);
|
||||
var result = await beacon_shop_item.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var beacon_shop_attribute = beacon_shop_item.getEntityAttribute<BeaconShopItemAttribute>();
|
||||
if (beacon_shop_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop attribute : {nameof(BeaconShopItemAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (beacon_shop_attribute.copyEntityAttributeFromDoc(doc) == false)
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromDoc !!! : doc_type {doc.GetType()} - {beacon_shop_item.getRootParent().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, beacon_shop_item);
|
||||
}
|
||||
|
||||
public static async Task<(Result, BeaconShopItem?)> createBeaconShop(UgcNpc owner, USER_GUID user_guid, BEACON_GUID beacon_guid, DateTime selling_finish_time, double price_for_unit, ushort amount, ItemAttributeBase deleted_item_attribute)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var beacon_shop_item = new BeaconShopItem(owner);
|
||||
var result = await beacon_shop_item.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to create onInit!!";
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var beacon_shop_attribute = beacon_shop_item.getEntityAttribute<BeaconShopItemAttribute>();
|
||||
if (beacon_shop_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop attribute : {nameof(BeaconShopItemAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
beacon_shop_attribute.UserGuid = user_guid;
|
||||
beacon_shop_attribute.BeaconGuid = beacon_guid;
|
||||
beacon_shop_attribute.SellingFinishTime = selling_finish_time;
|
||||
beacon_shop_attribute.PriceForUnit = price_for_unit;
|
||||
|
||||
beacon_shop_attribute.ItemMetaId = deleted_item_attribute.ItemMetaId;
|
||||
beacon_shop_attribute.ItemStackCount = amount;
|
||||
beacon_shop_attribute.Level = deleted_item_attribute.Level;
|
||||
beacon_shop_attribute.Attributes = deleted_item_attribute.Attributes.Select(x => x).ToList();
|
||||
beacon_shop_attribute.EquipedIvenType = deleted_item_attribute.EquipedIvenType;
|
||||
beacon_shop_attribute.EquipedPos = deleted_item_attribute.EquipedPos;
|
||||
|
||||
beacon_shop_attribute.newEntityAttribute();
|
||||
|
||||
return (result, beacon_shop_item);
|
||||
}
|
||||
|
||||
public override MetaAssets.ItemMetaData? getItemMeta()
|
||||
{
|
||||
var parent = getRootParent();
|
||||
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
||||
|
||||
var beacon_shop_item_attribute = getEntityAttribute<BeaconShopItemAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attribute, () => $"beacon_shop_item_attribute is null !!! - {parent.toBasicString()}");
|
||||
|
||||
if (!MetaData.Instance._ItemTable.TryGetValue((int)beacon_shop_item_attribute.ItemMetaId, out var found_item_meta_data))
|
||||
{
|
||||
var err_msg = $"Not found meta of Item !!! : itemMetaId:{beacon_shop_item_attribute.ItemMetaId} - {parent.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return null;
|
||||
}
|
||||
|
||||
return found_item_meta_data;
|
||||
}
|
||||
|
||||
public BeaconShopInfo toBeaconShopData4Client()
|
||||
{
|
||||
var beacon_shop_4_client = new BeaconShopInfo();
|
||||
|
||||
var beacon_shop_attribute = getEntityAttribute<BeaconShopItemAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_attribute, () => $"beacon_shop_attribute is null !!!");
|
||||
|
||||
beacon_shop_4_client.BeaconGuid = beacon_shop_attribute.BeaconGuid;
|
||||
beacon_shop_4_client.ItemGuid = beacon_shop_attribute.ItemGuid;
|
||||
beacon_shop_4_client.ItemMetaid = (int)beacon_shop_attribute.ItemMetaId;
|
||||
beacon_shop_4_client.SellingFinishTime = Timestamp.FromDateTime(beacon_shop_attribute.SellingFinishTime);
|
||||
beacon_shop_4_client.PriceForUnit = beacon_shop_attribute.PriceForUnit;
|
||||
beacon_shop_4_client.Amount = beacon_shop_attribute.ItemStackCount;
|
||||
|
||||
return beacon_shop_4_client;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
GameServer/Contents/BeaconShop/BeaconShopSoldPrice.cs
Normal file
62
GameServer/Contents/BeaconShop/BeaconShopSoldPrice.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class BeaconShopSoldPrice : EntityBase
|
||||
{
|
||||
public BeaconShopSoldPrice(EntityBase owner)
|
||||
: base(EntityType.BeaconShopSoldPrice, owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
addEntityAttribute(new BeaconShopSoldPriceAttribute(this));
|
||||
return await base.onInit();
|
||||
}
|
||||
|
||||
public override string toBasicString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public override string toSummaryString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public static async Task<(Result, BeaconShopSoldPrice?)> createBeaconShopSoldPriceFromDoc(Player owner, BeaconShopSoldPriceDoc doc)
|
||||
{
|
||||
var beacon_shop_sold_price = new BeaconShopSoldPrice(owner);
|
||||
var result = await beacon_shop_sold_price.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var beacon_shop_sold_price_attribute = beacon_shop_sold_price.getEntityAttribute<BeaconShopSoldPriceAttribute>();
|
||||
if (beacon_shop_sold_price_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop sold price attribute : {nameof(BeaconShopSoldPriceAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (beacon_shop_sold_price_attribute.copyEntityAttributeFromDoc(doc) == false)
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromDoc !!! : doc_type {doc.GetType()} - {beacon_shop_sold_price.getRootParent().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, beacon_shop_sold_price);
|
||||
}
|
||||
}
|
||||
83
GameServer/Contents/BeaconShop/BeaconShopSoldRecord.cs
Normal file
83
GameServer/Contents/BeaconShop/BeaconShopSoldRecord.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using BEACON_GUID = System.String;
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class BeaconShopSoldRecord : EntityBase
|
||||
{
|
||||
public BeaconShopSoldRecord(EntityBase owner)
|
||||
: base(EntityType.BeaconShopSoldRecord, owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
addEntityAttribute(new BeaconShopSoldRecordAttribute(this));
|
||||
return await base.onInit();
|
||||
}
|
||||
|
||||
public override string toBasicString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public override string toSummaryString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public static async Task<(Result, BeaconShopSoldRecord?)> createBeaconShopSoldRecordFromDoc(Player owner, BeaconShopSoldRecordDoc doc)
|
||||
{
|
||||
var beacon_shop_sold_record_item = new BeaconShopSoldRecord(owner);
|
||||
var result = await beacon_shop_sold_record_item.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var beacon_shop_sold_record_attribute = beacon_shop_sold_record_item.getEntityAttribute<BeaconShopSoldRecordAttribute>();
|
||||
if (beacon_shop_sold_record_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop sold record attribute : {nameof(BeaconShopSoldRecordAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (beacon_shop_sold_record_attribute.copyEntityAttributeFromDoc(doc) == false)
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromDoc !!! : doc_type {doc.GetType()} - {beacon_shop_sold_record_item.getRootParent().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, beacon_shop_sold_record_item);
|
||||
}
|
||||
|
||||
public BeaconShopSoldRecordInfo toBeaconShopSoldRecordData4Client()
|
||||
{
|
||||
var beacon_shop_sold_record_4_client = new BeaconShopSoldRecordInfo();
|
||||
|
||||
var beacon_shop_sold_record_attribute = getEntityAttribute<BeaconShopSoldRecordAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_sold_record_attribute, () => $"beacon_shop_sold_record_attribute is null !!!");
|
||||
|
||||
beacon_shop_sold_record_4_client.BeaconGuid = beacon_shop_sold_record_attribute.BeaconGuid;
|
||||
beacon_shop_sold_record_4_client.ItemMetaid = (int)beacon_shop_sold_record_attribute.ItemMetaId;
|
||||
beacon_shop_sold_record_4_client.BuyerNickName = beacon_shop_sold_record_attribute.BuyerNickName;
|
||||
beacon_shop_sold_record_4_client.PriceForUnit = beacon_shop_sold_record_attribute.PriceForUnit;
|
||||
beacon_shop_sold_record_4_client.Amount = beacon_shop_sold_record_attribute.Amount;
|
||||
beacon_shop_sold_record_4_client.SoldPrice = beacon_shop_sold_record_attribute.SoldPrice;
|
||||
beacon_shop_sold_record_4_client.TaxPrice = beacon_shop_sold_record_attribute.TaxPrice;
|
||||
beacon_shop_sold_record_4_client.GivenPrice = beacon_shop_sold_record_attribute.GivenPrice;
|
||||
|
||||
return beacon_shop_sold_record_4_client;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
using System.Globalization;
|
||||
|
||||
|
||||
using Amazon.DynamoDBv2;
|
||||
using Amazon.DynamoDBv2.DocumentModel;
|
||||
using Amazon.DynamoDBv2.Model;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class DBQBeaconShopItemDelete : QueryExecutorBase
|
||||
{
|
||||
private string m_combination_key_for_pk = string.Empty;
|
||||
|
||||
private string m_combination_key_for_sk = string.Empty;
|
||||
private double m_item_count { get; set; }
|
||||
|
||||
private PrimaryKey m_primary_key = new();
|
||||
|
||||
public DBQBeaconShopItemDelete(string combinationKeyForPK, string combinationKeyForSK, int itemCount) : base(nameof(DBQBeaconShopItemDelete))
|
||||
{
|
||||
m_item_count = itemCount;
|
||||
m_combination_key_for_pk = combinationKeyForPK;
|
||||
m_combination_key_for_sk = combinationKeyForSK;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onPrepareQuery()
|
||||
{
|
||||
var owner = getOwner();
|
||||
|
||||
var (result, make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<BeaconShopItemDoc>(m_combination_key_for_pk, m_combination_key_for_sk);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
|
||||
|
||||
m_primary_key = make_primary_key;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var owner = getOwner();
|
||||
|
||||
var query_batch = getQueryBatch() as QueryBatch<QueryRunnerWithItemRequest>;
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var query_runner_with_item_request = query_batch.getQueryRunner();
|
||||
NullReferenceCheckHelper.throwIfNull(query_runner_with_item_request, () => $"query_runner_with_item_request is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
|
||||
var table = db_connector.getTableByDoc<BeaconShopItemDoc>();
|
||||
var delete = makeDeleteItemRequestBeaconShopItem(table, m_primary_key.toKeyWithAttributeValue(), JsonHelper.getJsonPropertyName<BeaconShopItemAttrib>(nameof(BeaconShopItemAttrib.ItemStackCount)));
|
||||
if (delete.result.isFail()) return delete.result;
|
||||
NullReferenceCheckHelper.throwIfNull(delete.deleteRequest, () => $"deleteRequest is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var exception_handler = new DynamoDbQueryExceptionNotifier.ExceptionHandler(DynamoDbQueryExceptionNotifier.ConditionalCheckFailed, ServerErrorCode.BeaconShopUpdateNewData);
|
||||
|
||||
var query_context = delete.deleteRequest.createItemRequestQueryContext(QueryType.Delete, exception_handler);
|
||||
var result = await query_runner_with_item_request.tryRegisterQueryContext(query_context);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseCommit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
private (Result result, DeleteItemRequest? deleteRequest) makeDeleteItemRequestBeaconShopItem( Table table
|
||||
, Dictionary<string, AttributeValue> attributeValueWithPrimaryKey
|
||||
, string targetAttribName )
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
if (string.IsNullOrEmpty(targetAttribName))
|
||||
{
|
||||
err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : targetAttribName - {targetAttribName}";
|
||||
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var query_builder = new DynamoDbItemRequestHelper.DeleteItemRequestBuilder(table.TableName);
|
||||
query_builder.withKeys(attributeValueWithPrimaryKey);
|
||||
query_builder.withConditionExpression($"attribute_exists({PrimaryKey.PK_Define}) AND attribute_exists({PrimaryKey.SK_Define})");
|
||||
|
||||
var target_doc = new BeaconShopItemDoc();
|
||||
var attrib_path_json_string = target_doc.toJsonStringOfAttribs();
|
||||
(var is_success, var attribute_expression) = DynamoDbClientHelper.toAttributeExpressionFromJson(attrib_path_json_string, targetAttribName);
|
||||
if (false == is_success)
|
||||
{
|
||||
err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : attribPath:{attrib_path_json_string}, targetKey:{targetAttribName}";
|
||||
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var attribute_names = DynamoDbClientHelper.toExpressionAttributeNamesFromJson(attrib_path_json_string, targetAttribName);
|
||||
query_builder.withExpressionAttributeNames(attribute_names);
|
||||
query_builder.withConditionExpression($"{attribute_expression} = :changeValue");
|
||||
|
||||
var expression_attribute_values = new Dictionary<string, AttributeValue>
|
||||
{
|
||||
{ ":changeValue", new AttributeValue { N = Math.Abs(m_item_count).ToString(CultureInfo.InvariantCulture) } }
|
||||
};
|
||||
query_builder.withExpressionAttributeValues(expression_attribute_values);
|
||||
|
||||
query_builder.withReturnValues(ReturnValue.ALL_NEW);
|
||||
|
||||
return (result, query_builder.build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using System.Globalization;
|
||||
|
||||
|
||||
using Amazon.DynamoDBv2;
|
||||
using Amazon.DynamoDBv2.DocumentModel;
|
||||
using Amazon.DynamoDBv2.Model;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class DBQBeaconShopItemUpdate : QueryExecutorBase
|
||||
{
|
||||
private string m_combination_key_for_pk = string.Empty;
|
||||
|
||||
private string m_combination_key_for_sk = string.Empty;
|
||||
private double m_delta { get; set; }
|
||||
|
||||
private PrimaryKey m_primary_key = new();
|
||||
|
||||
//=====================================================================================
|
||||
// 0 < deltaCount => 증가
|
||||
// 0 > deltaCount => 감소
|
||||
//=====================================================================================
|
||||
|
||||
public DBQBeaconShopItemUpdate(string combinationKeyForPK, string combinationKeyForSK, double delta) : base(nameof(DBQBeaconShopItemUpdate))
|
||||
{
|
||||
m_delta = delta;
|
||||
m_combination_key_for_pk = combinationKeyForPK;
|
||||
m_combination_key_for_sk = combinationKeyForSK;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onPrepareQuery()
|
||||
{
|
||||
var owner = getOwner();
|
||||
|
||||
var (result, make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<BeaconShopItemDoc>(m_combination_key_for_pk, m_combination_key_for_sk);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
|
||||
|
||||
m_primary_key = make_primary_key;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var owner = getOwner();
|
||||
|
||||
var query_batch = getQueryBatch() as QueryBatch<QueryRunnerWithItemRequest>;
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var query_runner_with_item_request = query_batch.getQueryRunner();
|
||||
NullReferenceCheckHelper.throwIfNull(query_runner_with_item_request, () => $"query_runner_with_item_request is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
|
||||
var table = db_connector.getTableByDoc<BeaconShopItemDoc>();
|
||||
var update = makeUpdateItemRequestUpdateBeaconShopItemCount(table, m_primary_key.toKeyWithAttributeValue(), JsonHelper.getJsonPropertyName<BeaconShopItemAttrib>(nameof(BeaconShopItemAttrib.ItemStackCount)));
|
||||
if (update.result.isFail()) return update.result;
|
||||
NullReferenceCheckHelper.throwIfNull(update.updateRequest, () => $"update_request is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var exception_handler = new DynamoDbQueryExceptionNotifier.ExceptionHandler(DynamoDbQueryExceptionNotifier.ConditionalCheckFailed, ServerErrorCode.BeaconShopUpdateNewData);
|
||||
|
||||
var query_context = update.updateRequest.createItemRequestQueryContext(QueryType.Update, exception_handler);
|
||||
var result = await query_runner_with_item_request.tryRegisterQueryContext(query_context);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseCommit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
private (Result result, UpdateItemRequest? updateRequest) makeUpdateItemRequestUpdateBeaconShopItemCount( Table table
|
||||
, Dictionary<string, AttributeValue> attributeValueWithPrimaryKey
|
||||
, string targetAttribName )
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
if (string.IsNullOrEmpty(targetAttribName))
|
||||
{
|
||||
err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : targetAttribName - {targetAttribName}";
|
||||
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var query_builder = new DynamoDbItemRequestHelper.UpdateItemRequestBuilder(table.TableName);
|
||||
query_builder.withKeys(attributeValueWithPrimaryKey);
|
||||
|
||||
var target_doc = new BeaconShopItemDoc();
|
||||
var attrib_path_json_string = target_doc.toJsonStringOfAttribs();
|
||||
(var is_success, var attribute_expression) = DynamoDbClientHelper.toAttributeExpressionFromJson(attrib_path_json_string, targetAttribName);
|
||||
if (false == is_success)
|
||||
{
|
||||
err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : attribPath:{attrib_path_json_string}, targetKey:{targetAttribName}";
|
||||
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var attribute_names = DynamoDbClientHelper.toExpressionAttributeNamesFromJson(attrib_path_json_string, targetAttribName);
|
||||
query_builder.withExpressionAttributeNames(attribute_names);
|
||||
|
||||
var update_expression = (m_delta >= 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);
|
||||
|
||||
if (m_delta < 0)
|
||||
{
|
||||
query_builder.withConditionExpression($"{attribute_expression} >= :changeValue");
|
||||
}
|
||||
|
||||
var expression_attribute_values = new Dictionary<string, AttributeValue>
|
||||
{
|
||||
{ ":changeValue", new AttributeValue { N = Math.Abs(m_delta).ToString(CultureInfo.InvariantCulture) } },
|
||||
{ ":start", new AttributeValue { N = "0" } }
|
||||
};
|
||||
query_builder.withExpressionAttributeValues(expression_attribute_values);
|
||||
|
||||
query_builder.withReturnValues(ReturnValue.ALL_NEW);
|
||||
|
||||
return query_builder.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using Amazon.DynamoDBv2.DocumentModel;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class DBQBeaconShopSoldReadAll : QueryExecutorBase
|
||||
{
|
||||
private string m_combination_key_for_pk = string.Empty;
|
||||
|
||||
private string m_recoed_pk = string.Empty;
|
||||
private string m_price_pk = string.Empty;
|
||||
|
||||
private List<BeaconShopSoldRecordDoc> m_to_read_beacon_shop_sold_record_docs = new();
|
||||
private List<BeaconShopSoldPriceDoc> m_to_read_beacon_shop_sold_price_docs = new();
|
||||
|
||||
public DBQBeaconShopSoldReadAll(string combinationKeyForPK)
|
||||
: base(typeof(DBQBeaconShopSoldReadAll).Name)
|
||||
{
|
||||
m_combination_key_for_pk = combinationKeyForPK;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//=====================================================================================
|
||||
public override Task<Result> onPrepareQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var record_doc = new BeaconShopSoldRecordDoc();
|
||||
record_doc.setCombinationKeyForPK(m_combination_key_for_pk);
|
||||
|
||||
var error_code = record_doc.onApplyPKSK();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(error_code, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
m_recoed_pk = record_doc.getPK();
|
||||
|
||||
var price_doc = new BeaconShopSoldPriceDoc();
|
||||
price_doc.setCombinationKeyForPK(m_combination_key_for_pk);
|
||||
|
||||
error_code = price_doc.onApplyPKSK();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(error_code, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
m_price_pk = price_doc.getPK();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var query_batch = getQueryBatch();
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => "query_batch is null !!!");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
var query_config = db_connector.makeQueryConfigForReadByPKOnly(m_recoed_pk);
|
||||
|
||||
(result, var record_read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopSoldRecordDoc>(query_config, eventTid: query_batch.getTransId());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var beacon_shop_inventory_action = owner.getEntityAction<BeaconShopAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_inventory_action, () => "beacon_shop_inventory_action is null !!!");
|
||||
|
||||
result = await beacon_shop_inventory_action.AddBeaconShopSoldRecordsFromDocs(record_read_docs);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var price_query_config = db_connector.makeQueryConfigForReadByPKOnly(m_price_pk);
|
||||
|
||||
(result, var price_read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopSoldPriceDoc>(price_query_config, eventTid: query_batch.getTransId());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_inventory_action.AddBeaconShopSoldPriceFromDocs(price_read_docs);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_inventory_action.ProcessBeaconShopDeleteRecord();
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
m_to_read_beacon_shop_sold_record_docs = record_read_docs;
|
||||
m_to_read_beacon_shop_sold_price_docs = price_read_docs;
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
public List<BeaconShopSoldRecordDoc> getToReadItemDocs() => m_to_read_beacon_shop_sold_record_docs;
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseCommit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
public new Player? getOwner() => getQueryBatch()?.getLogActor() as Player;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using Amazon.DynamoDBv2.DocumentModel;
|
||||
using GameServer;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class DBQBeaconShopSoldRecordReadAll : QueryExecutorBase
|
||||
{
|
||||
private string m_combination_key_for_pk = string.Empty;
|
||||
|
||||
private string m_pk = string.Empty;
|
||||
|
||||
private List<BeaconShopSoldRecordDoc> m_to_read_beacon_shop_sold_record_docs = new();
|
||||
|
||||
public DBQBeaconShopSoldRecordReadAll(string combinationKeyForPK)
|
||||
: base(typeof(DBQBeaconShopSoldRecordReadAll).Name)
|
||||
{
|
||||
m_combination_key_for_pk = combinationKeyForPK;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//=====================================================================================
|
||||
public override Task<Result> onPrepareQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var doc = new BeaconShopSoldRecordDoc();
|
||||
doc.setCombinationKeyForPK(m_combination_key_for_pk);
|
||||
|
||||
var error_code = doc.onApplyPKSK();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(error_code, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
m_pk = doc.getPK();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var query_batch = getQueryBatch();
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => "query_batch is null !!!");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
var query_config = db_connector.makeQueryConfigForReadByPKOnly(m_pk);
|
||||
|
||||
(result, var read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopSoldRecordDoc>(query_config, eventTid: query_batch.getTransId());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var beacon_shop_inventory_action = owner.getEntityAction<BeaconShopAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_inventory_action, () => "beacon_shop_inventory_action is null !!!");
|
||||
|
||||
result = await beacon_shop_inventory_action.AddBeaconShopSoldRecordsFromDocs(read_docs);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
m_to_read_beacon_shop_sold_record_docs = read_docs;
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
public List<BeaconShopSoldRecordDoc> getToReadItemDocs() => m_to_read_beacon_shop_sold_record_docs;
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseCommit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
public new Player? getOwner() => getQueryBatch()?.getLogActor() as Player;
|
||||
}
|
||||
}
|
||||
121
GameServer/Contents/BeaconShop/Helper/BeaconShopHelper.cs
Normal file
121
GameServer/Contents/BeaconShop/Helper/BeaconShopHelper.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using ServerCommon;
|
||||
using USER_GUID = System.String;
|
||||
using BEACON_GUID = System.String;
|
||||
using META_ID = System.UInt32;
|
||||
using ServerCore; using ServerBase;
|
||||
using static ServerMessage.Types;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
internal static class BeaconShopHelper
|
||||
{
|
||||
public static BeaconShopItemBoardInfo toBeaconShopItemMongoDataClient(this BeaconShopMongoDoc beaconShopMongoDoc)
|
||||
{
|
||||
var beacon_shop_4_client = new BeaconShopItemBoardInfo();
|
||||
|
||||
beacon_shop_4_client.ItemGuid = beaconShopMongoDoc.ItemGuid;
|
||||
beacon_shop_4_client.ItemMetaid = (int)beaconShopMongoDoc.TagId;
|
||||
beacon_shop_4_client.BeaconGuid = beaconShopMongoDoc.BeaconGuid;
|
||||
beacon_shop_4_client.BeaconNickName = beaconShopMongoDoc.BeaconNickName;
|
||||
beacon_shop_4_client.BeaconTitle = beaconShopMongoDoc.BeaconTitle;
|
||||
beacon_shop_4_client.BeaconBodyItemMetaId = beaconShopMongoDoc.BeaconBodyItemMetaId;
|
||||
beacon_shop_4_client.PriceForUnit = beaconShopMongoDoc.PriceForUnit;
|
||||
beacon_shop_4_client.Amount = beaconShopMongoDoc.Amount;
|
||||
beacon_shop_4_client.OwnerGuid = beaconShopMongoDoc.OwnerGuid;
|
||||
beacon_shop_4_client.OwnerNickName = beaconShopMongoDoc.OwnerNickName;
|
||||
beacon_shop_4_client.BeaconMyHomeGuid = beaconShopMongoDoc.BeaconMyHomeGuid;
|
||||
beacon_shop_4_client.SellingFinishTime = Timestamp.FromDateTime(beaconShopMongoDoc.SellingFinishTime);
|
||||
|
||||
return beacon_shop_4_client;
|
||||
}
|
||||
|
||||
public async static Task<BeaconShopSoldRecordDoc?> CreateBeaconShopSoldRecord(BeaconShopItemAttribute beaconShopItemAttribute, string buyerNickName, int amount, double soldPrice, double taxPrice, double givenPrice)
|
||||
{
|
||||
DateTime now = DateTimeHelper.Current;
|
||||
|
||||
var beacon_shop_sold_record_doc = new BeaconShopSoldRecordDoc(beaconShopItemAttribute.UserGuid, now);
|
||||
|
||||
var beacon_shop_sold_record_attrib = beacon_shop_sold_record_doc.getAttrib<BeaconShopSoldRecordAttrib>();
|
||||
if (beacon_shop_sold_record_attrib == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
beacon_shop_sold_record_attrib.UserGuid = beaconShopItemAttribute.UserGuid;
|
||||
beacon_shop_sold_record_attrib.BeaconGuid = beaconShopItemAttribute.BeaconGuid;
|
||||
beacon_shop_sold_record_attrib.ItemMetaId = beaconShopItemAttribute.ItemMetaId;
|
||||
beacon_shop_sold_record_attrib.BuyerNickName = buyerNickName;
|
||||
beacon_shop_sold_record_attrib.PriceForUnit = beaconShopItemAttribute.PriceForUnit;
|
||||
beacon_shop_sold_record_attrib.Amount = amount;
|
||||
beacon_shop_sold_record_attrib.SalesTime = now;
|
||||
beacon_shop_sold_record_attrib.SoldPrice = soldPrice;
|
||||
beacon_shop_sold_record_attrib.TaxPrice = taxPrice;
|
||||
beacon_shop_sold_record_attrib.GivenPrice = givenPrice;
|
||||
|
||||
var result = await beacon_shop_sold_record_doc.newDoc4Query();
|
||||
if (result.isFail())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return beacon_shop_sold_record_doc;
|
||||
}
|
||||
|
||||
public static void send_GS2GS_NTF_UPDATE_SOLD_RECORD(string targetServer, USER_GUID targetUserGuid)
|
||||
{
|
||||
ConditionValidCheckHelper.throwIfFalseWithCondition(() => true != targetServer.isNullOrWhiteSpace()
|
||||
, () => $"targetServer is NullOrWhiteSpace !!! - targetServer:{targetServer}, targetUserGuid:{targetUserGuid}");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var rabbit_mq_4_game = server_logic.getRabbitMqConnector() as RabbitMQ4Game;
|
||||
NullReferenceCheckHelper.throwIfNull(rabbit_mq_4_game, () => $"rabbit_mq_4_game is null !!");
|
||||
|
||||
var ntf_packet = new ServerMessage();
|
||||
var ntf_update_sold_record = new GS2GS_NTF_UPDATE_SOLD_RECORD();
|
||||
ntf_packet.NtfUpdateSoldRecord = ntf_update_sold_record;
|
||||
|
||||
ntf_update_sold_record.TargetUserGuid = targetUserGuid;
|
||||
|
||||
rabbit_mq_4_game.SendMessage(targetServer, ntf_packet);
|
||||
}
|
||||
|
||||
public static void send_GS2GS_NTF_UPDATE_BEACON_SHOP_ITEM(USER_GUID targetUserGuid, BEACON_GUID targetBeaconGuid)
|
||||
{
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var rabbit_mq_4_game = server_logic.getRabbitMqConnector() as RabbitMQ4Game;
|
||||
NullReferenceCheckHelper.throwIfNull(rabbit_mq_4_game, () => $"rabbit_mq_4_game is null !!");
|
||||
|
||||
var ntf_packet = new ServerMessage();
|
||||
var ntf_update_beacon_shop_item = new GS2GS_NTF_UPDATE_BEACON_SHOP_ITEM();
|
||||
ntf_packet.NtfUpdateBeaconShopItem = ntf_update_beacon_shop_item;
|
||||
|
||||
ntf_update_beacon_shop_item.TargetUserGuid = targetUserGuid;
|
||||
ntf_update_beacon_shop_item.TargetBeaconGuid = targetBeaconGuid;
|
||||
|
||||
rabbit_mq_4_game.sendMessageToExchangeAllGame(ntf_packet);
|
||||
}
|
||||
|
||||
public static ItemDoc toItemDocFromBeaconShopItemDoc(BeaconShopItemDoc beaconShopItemDoc, ushort itemStackCount)
|
||||
{
|
||||
var beacon_shop_item_attrib = beaconShopItemDoc.getAttrib<BeaconShopItemAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attrib, () => $"beacon_shop_item_attrib is null !!");
|
||||
|
||||
var item_guid = Guid.NewGuid().ToString("N");
|
||||
var itemDoc = new ItemDoc(beacon_shop_item_attrib.OwnerEntityType, beacon_shop_item_attrib.UserGuid, item_guid);
|
||||
|
||||
var item_attrib = itemDoc.getAttrib<ItemAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(item_attrib, () => $"item_attrib is null !!!");
|
||||
item_attrib.ItemMetaId = beacon_shop_item_attrib.ItemMetaId;
|
||||
item_attrib.ItemStackCount = itemStackCount;
|
||||
item_attrib.Level = beacon_shop_item_attrib.Level;
|
||||
item_attrib.Attributes = beacon_shop_item_attrib.Attributes.Select(x => x).ToList();
|
||||
item_attrib.EquipedIvenType = beacon_shop_item_attrib.EquipedIvenType;
|
||||
item_attrib.EquipedPos = beacon_shop_item_attrib.EquipedPos;
|
||||
|
||||
return itemDoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
GameServer/Contents/BeaconShop/Log/BeaconShopBusinessLog.cs
Normal file
33
GameServer/Contents/BeaconShop/Log/BeaconShopBusinessLog.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class BeaconShopBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private BeaconShopLogData m_data_to_log;
|
||||
public BeaconShopBusinessLog(BeaconShopLogData log_data_param)
|
||||
: base(LogDomainType.BeaconShop)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new BeaconShopLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using ServerCommon;
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
static public class BeaconShopBusinessLogHelper
|
||||
{
|
||||
static public BeaconShopLogData toLogInfo(BeaconShopMongoDoc beaconShopMongoDoc)
|
||||
{
|
||||
var logData = new BeaconShopLogData();
|
||||
logData.setInfo(beaconShopMongoDoc);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this BeaconShopLogData logData, BeaconShopMongoDoc beaconShopMongoDoc)
|
||||
{
|
||||
logData.ItemGuid = beaconShopMongoDoc.ItemGuid;
|
||||
logData.TagId = beaconShopMongoDoc.TagId;
|
||||
logData.BeaconGuid = beaconShopMongoDoc.BeaconGuid;
|
||||
logData.BeaconNickName = beaconShopMongoDoc.BeaconNickName;
|
||||
logData.BeaconTitle = beaconShopMongoDoc.BeaconTitle;
|
||||
logData.BeaconBodyItemMetaId = beaconShopMongoDoc.BeaconBodyItemMetaId;
|
||||
logData.PriceForUnit = beaconShopMongoDoc.PriceForUnit;
|
||||
logData.Amount = beaconShopMongoDoc.Amount;
|
||||
logData.OwnerGuid = beaconShopMongoDoc.OwnerGuid;
|
||||
logData.OwnerNickName = beaconShopMongoDoc.OwnerNickName;
|
||||
logData.BeaconMyHomeGuid = beaconShopMongoDoc.BeaconMyHomeGuid;
|
||||
logData.SellingFinishTime = beaconShopMongoDoc.SellingFinishTime;
|
||||
logData.BuyerGuid = string.Empty;
|
||||
}
|
||||
|
||||
static public BeaconShopLogData toLogInfo(BeaconShopItemAttribute beaconShopItemAttribute, UgcNpcAttribute ugcNpcAttribute, string buyerGuid)
|
||||
{
|
||||
var logData = new BeaconShopLogData();
|
||||
logData.setInfo(beaconShopItemAttribute, ugcNpcAttribute, buyerGuid);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this BeaconShopLogData logData, BeaconShopItemAttribute beaconShopItemAttribute, UgcNpcAttribute ugcNpcAttribute, string buyerGuid)
|
||||
{
|
||||
logData.ItemGuid = beaconShopItemAttribute.ItemGuid;
|
||||
logData.TagId = (int)beaconShopItemAttribute.ItemMetaId;
|
||||
logData.BeaconGuid = beaconShopItemAttribute.BeaconGuid;
|
||||
logData.BeaconNickName = ugcNpcAttribute.Nickname;
|
||||
logData.BeaconTitle = ugcNpcAttribute.Title;
|
||||
logData.BeaconBodyItemMetaId = (int)ugcNpcAttribute.BodyItemMetaId;
|
||||
logData.PriceForUnit = beaconShopItemAttribute.PriceForUnit;
|
||||
logData.Amount = beaconShopItemAttribute.ItemStackCount;
|
||||
logData.OwnerGuid = beaconShopItemAttribute.UserGuid;
|
||||
logData.BeaconMyHomeGuid = ugcNpcAttribute.LocatedInstanceGuid;
|
||||
logData.SellingFinishTime = beaconShopItemAttribute.SellingFinishTime;
|
||||
logData.BuyerGuid = buyerGuid;
|
||||
}
|
||||
|
||||
static public BeaconShopSoldRecordLogData toLogInfo(BeaconShopSoldRecordAttribute beaconShopSoldRecordAttribute)
|
||||
{
|
||||
var logData = new BeaconShopSoldRecordLogData();
|
||||
logData.setInfo(beaconShopSoldRecordAttribute);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this BeaconShopSoldRecordLogData logData, BeaconShopSoldRecordAttribute beaconShopSoldRecordAttribute)
|
||||
{
|
||||
logData.UserGuid = beaconShopSoldRecordAttribute.UserGuid;
|
||||
logData.BeaconGuid = beaconShopSoldRecordAttribute.BeaconGuid;
|
||||
logData.ItemMetaId = beaconShopSoldRecordAttribute.ItemMetaId;
|
||||
logData.BuyerNickName = beaconShopSoldRecordAttribute.BuyerNickName;
|
||||
logData.PriceForUnit = beaconShopSoldRecordAttribute.PriceForUnit;
|
||||
logData.Amount = beaconShopSoldRecordAttribute.Amount;
|
||||
logData.SalesTime = beaconShopSoldRecordAttribute.SalesTime;
|
||||
}
|
||||
|
||||
static public BeaconShopSoldPriceLogData toLogInfo(string userGuid, string beaconGuid, double deltaPrice, double deltaTaxPrice)
|
||||
{
|
||||
var logData = new BeaconShopSoldPriceLogData();
|
||||
logData.setInfo(userGuid, beaconGuid, deltaPrice, deltaTaxPrice);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this BeaconShopSoldPriceLogData logData, string userGuid, string beaconGuid, double deltaPrice, double deltaTaxPrice)
|
||||
{
|
||||
logData.UserGuid = userGuid;
|
||||
logData.BeaconGuid = beaconGuid;
|
||||
logData.deltaPrice = deltaPrice;
|
||||
logData.deltaTaxPrice = deltaTaxPrice;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class BeaconShopSoldPriceBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private BeaconShopSoldPriceLogData m_data_to_log;
|
||||
public BeaconShopSoldPriceBusinessLog(BeaconShopSoldPriceLogData log_data_param)
|
||||
: base(LogDomainType.BeaconShopSoldPrice)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new BeaconShopSoldPriceLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class BeaconShopSoldRecordBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private BeaconShopSoldRecordLogData m_data_to_log;
|
||||
public BeaconShopSoldRecordBusinessLog(BeaconShopSoldRecordLogData log_data_param)
|
||||
: base(LogDomainType.BeaconShopSoldRecord)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new BeaconShopSoldRecordLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
26
GameServer/Contents/BeaconShop/MongoDb/BeaconShopMongoDoc.cs
Normal file
26
GameServer/Contents/BeaconShop/MongoDb/BeaconShopMongoDoc.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
|
||||
public class BeaconShopMongoDoc
|
||||
{
|
||||
[BsonId]
|
||||
[BsonRepresentation(BsonType.ObjectId)]
|
||||
public string Id { get; set; } = null!;
|
||||
public string ItemGuid { get; set; } = null!;
|
||||
public int TagId { get; set; } = 0;
|
||||
public string BeaconGuid { get; set; } = null!;
|
||||
public string BeaconNickName { get; set; } = null!;
|
||||
public string BeaconTitle { get; set; } = string.Empty;
|
||||
public int BeaconBodyItemMetaId { get; set; } = 0;
|
||||
public double PriceForUnit { get; set; } = 0;
|
||||
public int Amount { get; set; } = 0;
|
||||
public string OwnerGuid { get; set; } = null!;
|
||||
public string OwnerNickName { get; set; } = null!;
|
||||
public string BeaconMyHomeGuid { get; set; } = null!;
|
||||
[BsonRequired]
|
||||
public DateTime SellingFinishTime { get; set; } = new();
|
||||
}
|
||||
|
||||
134
GameServer/Contents/BeaconShop/MongoDb/BeaconShopRepository.cs
Normal file
134
GameServer/Contents/BeaconShop/MongoDb/BeaconShopRepository.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
using MongoDB.Driver;
|
||||
|
||||
|
||||
using ServerBase;
|
||||
using ServerCore;
|
||||
|
||||
|
||||
using BEACON_GUID = System.String;
|
||||
using META_ID = System.UInt32;
|
||||
using USER_GUID = System.String;
|
||||
using ITEM_GUID = System.String;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class BeaconShopRepository : MongoDbRepository<BeaconShopMongoDoc>
|
||||
{
|
||||
private const string CollectionName = "BeaconShop";
|
||||
|
||||
public BeaconShopRepository(IMongoClient mongoClient, MongoDbConf settings) :
|
||||
base(mongoClient, settings.DatabaseName, CollectionName)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<(Result, List<BeaconShopMongoDoc>?)> get(int tagId)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var builder = Builders<BeaconShopMongoDoc>.Filter;
|
||||
var filter = builder.Eq(x => x.TagId, tagId);
|
||||
|
||||
try
|
||||
{
|
||||
var findData = await m_collection.FindAsync(filter);
|
||||
return (result, findData.ToList());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
err_msg = $"MongoDB Write Exception Error: {ex.Message}";
|
||||
result.setFail(ServerErrorCode.BeaconShopFailedGetBoardItem, err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result> insert(BeaconShopMongoDoc beaconShopEntity)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
await m_collection.InsertOneAsync(beaconShopEntity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
err_msg = $"MongoDB Write Exception Error: {ex.Message}";
|
||||
result.setFail(ServerErrorCode.BeaconShopFailedRegisterBoard, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<(Result, BeaconShopMongoDoc?)> updateAmount(string id, int amount)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var filter = Builders<BeaconShopMongoDoc>.Filter
|
||||
.Eq(x => x.ItemGuid, id);
|
||||
|
||||
var update = Builders<BeaconShopMongoDoc>.Update
|
||||
.Inc(x => x.Amount, amount);
|
||||
|
||||
var options = new FindOneAndUpdateOptions<BeaconShopMongoDoc>
|
||||
{
|
||||
ReturnDocument = ReturnDocument.After,
|
||||
};
|
||||
|
||||
var updated = await m_collection.FindOneAndUpdateAsync(filter, update, options);
|
||||
|
||||
if (updated == null)
|
||||
{
|
||||
err_msg = $"MongoDB is already empty. Error";
|
||||
result.setFail(ServerErrorCode.BeaconShopFailedToFindOrUpdate, err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (updated.Amount == 0)
|
||||
{
|
||||
return (await delete(id), updated);
|
||||
}
|
||||
return (result, updated);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
err_msg = $"MongoDB Write Exception Error: {ex.Message}";
|
||||
result.setFail(ServerErrorCode.BeaconShopDbException, err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result> delete(ITEM_GUID item_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var builder = Builders<BeaconShopMongoDoc>.Filter;
|
||||
var filter = builder.Eq(x => x.ItemGuid, item_guid);
|
||||
|
||||
try
|
||||
{
|
||||
var db_result = await m_collection.DeleteOneAsync(filter);
|
||||
if (db_result.DeletedCount == 0)
|
||||
{
|
||||
result.setFail(ServerErrorCode.BeaconShopNotFoundItemFromBoard, err_msg);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
err_msg = $"MongoDB Delete Exception Error : {ex.Message}";
|
||||
result.setFail(ServerErrorCode.BeaconShopFailedDeleteBoard, err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_SHOP_GET_ITEM_INFOS), typeof(BeaconShopGetItemInfosPacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconShopGetItemInfosPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BEACON_SHOP_GET_ITEM_INFOS(Player player, Result result, List<BeaconShopItem>? beaconShopItem = null, int dailyRegisterCount = 0, int numOfReceiptNotReceived = 0)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckBeaconShopGetItemInfos = new GS2C_ACK_BEACON_SHOP_GET_ITEM_INFOS();
|
||||
|
||||
if (result.isSuccess() && beaconShopItem != null)
|
||||
{
|
||||
ack_packet.Response.AckBeaconShopGetItemInfos.BeaconShopInfos.AddRange(beaconShopItem.Select<BeaconShopItem, BeaconShopInfo>(x => x.toBeaconShopData4Client()).ToList());
|
||||
ack_packet.Response.AckBeaconShopGetItemInfos.DailyRegisterCount = dailyRegisterCount;
|
||||
ack_packet.Response.AckBeaconShopGetItemInfos.NumOfReceiptNotReceived = numOfReceiptNotReceived;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
|
||||
|
||||
var beacon_shop_action = entity_player.getEntityAction<BeaconShopAction>();
|
||||
if (beacon_shop_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop action : {nameof(BeaconShopAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_ITEM_INFOS(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ReqBeaconShopGetItemInfos)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_ITEM_INFOS(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ReqBeaconShopGetItemInfos;
|
||||
|
||||
if (request.BeaconGuid == string.Empty && request.BeaconOwnerGuid == string.Empty)
|
||||
{
|
||||
err_msg = $"Invalid Request Argument !!! : BeaconGuid : {request.BeaconGuid}, BeaconOwnerGuid : {request.BeaconOwnerGuid}";
|
||||
result.setFail(ServerErrorCode.BeaconShopInvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_ITEM_INFOS(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_action.BeaconShopGetItemInfos(request.BeaconGuid, request.BeaconOwnerGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_BEACON_SHOP_GET_ITEM_INFOS(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_ITEM_INFOS(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using ServerCore; using ServerBase;
|
||||
using BEACON_GUID = System.String;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public static class BeaconShopNotifyHelper
|
||||
{
|
||||
public static bool send_S2C_NTF_BEACON_SHOP_REFRESH(this Player player, BEACON_GUID beaconGuid)
|
||||
{
|
||||
var noti_packet = makeAckBeaconShopRefreshPacket(beaconGuid);
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, noti_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ClientToGame makeAckBeaconShopRefreshPacket(BEACON_GUID beaconGuid)
|
||||
{
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.NtfBeaconShopRefresh = new();
|
||||
|
||||
noti_packet.Message.NtfBeaconShopRefresh.BeaconGuid = beaconGuid;
|
||||
|
||||
return noti_packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_SHOP_PURCHASE_ITEM), typeof(BeaconShopPurchaseItemPacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconShopPurchaseItemPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(Player player, Result result, string itemGuid = "", string beaconGuid = "", int itemAmount = 0, CommonResult? commonResult = null)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckBeaconShopPurchaseItem = new GS2C_ACK_BEACON_SHOP_PURCHASE_ITEM();
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ack_packet.Response.AckBeaconShopPurchaseItem.ItemGuid = itemGuid;
|
||||
ack_packet.Response.AckBeaconShopPurchaseItem.BeaconGuid = beaconGuid;
|
||||
ack_packet.Response.AckBeaconShopPurchaseItem.ItemAmount = itemAmount;
|
||||
ack_packet.Response.AckBeaconShopPurchaseItem.CommonResult = commonResult;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!" );
|
||||
|
||||
var beacon_shop_action = entity_player.getEntityAction<BeaconShopAction>();
|
||||
if (beacon_shop_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop action : {nameof(BeaconShopAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ReqBeaconShopPurchaseItem)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ReqBeaconShopPurchaseItem;
|
||||
|
||||
if(request.ItemGuid == string.Empty ||
|
||||
request.BeaconGuid == string.Empty ||
|
||||
request.ItemAmount <= 0 ||
|
||||
request.BeaconOwnerGuid == string.Empty)
|
||||
{
|
||||
err_msg = $"Invalid Request Argument !!! : ItemGuid : {request.ItemGuid}, BeaconGuid : {request.BeaconGuid}, ItemAmount : {request.ItemAmount}";
|
||||
result.setFail(ServerErrorCode.BeaconShopInvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_action.BeaconShopPurchaseItem(request.ItemGuid, (UInt16)request.ItemAmount, request.BeaconGuid, request.BeaconOwnerGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES), typeof(BeaconShopReceivePaymentForSalesPacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconShopReceivePaymentForSalesPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(Player player, Result result, string beaconGuid = "", CommonResult? commonResult = null)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckBeaconShopReceivePaymentForSales = new GS2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES();
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ack_packet.Response.AckBeaconShopReceivePaymentForSales.BeaconGuid = beaconGuid;
|
||||
ack_packet.Response.AckBeaconShopReceivePaymentForSales.CommonResult = commonResult;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!" );
|
||||
|
||||
var beacon_shop_action = entity_player.getEntityAction<BeaconShopAction>();
|
||||
if (beacon_shop_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop action : {nameof(BeaconShopAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ReqBeaconShopReceivePaymentForSales)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ReqBeaconShopReceivePaymentForSales;
|
||||
|
||||
if (request.BeaconGuid == string.Empty)
|
||||
{
|
||||
err_msg = $"Invalid Request Argument !!! : BeaconGuid : {request.BeaconGuid}";
|
||||
result.setFail(ServerErrorCode.BeaconShopInvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_action.BeaconShopReceivePaymentForSales(request.BeaconGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_SHOP_REGISTER_ITEM), typeof(BeaconShopRegisterItemPacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconShopRegisterItemPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(Player player, Result result, BeaconShopItem? beaconShopItem, CommonResult? commonResult = null)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckBeaconShopRegisterItem = new GS2C_ACK_BEACON_SHOP_REGISTER_ITEM();
|
||||
|
||||
if (result.isSuccess() && beaconShopItem != null)
|
||||
{
|
||||
var beacon_shop_attribute = beaconShopItem.getEntityAttribute<BeaconShopItemAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(beacon_shop_attribute, () => $"beacon_shop_attribute is null !!!");
|
||||
|
||||
ack_packet.Response.AckBeaconShopRegisterItem.ItemGuid = beacon_shop_attribute.ItemGuid;
|
||||
ack_packet.Response.AckBeaconShopRegisterItem.ItemMetaId = (int)beacon_shop_attribute.ItemMetaId;
|
||||
ack_packet.Response.AckBeaconShopRegisterItem.ItemAmount = beacon_shop_attribute.ItemStackCount;
|
||||
ack_packet.Response.AckBeaconShopRegisterItem.SellingPrice = beacon_shop_attribute.PriceForUnit;
|
||||
ack_packet.Response.AckBeaconShopRegisterItem.BeaconGuid = beacon_shop_attribute.BeaconGuid;
|
||||
ack_packet.Response.AckBeaconShopRegisterItem.SellingFinishTime = Timestamp.FromDateTime(beacon_shop_attribute.SellingFinishTime);
|
||||
ack_packet.Response.AckBeaconShopRegisterItem.CommonResult = commonResult;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!" );
|
||||
|
||||
var beacon_shop_action = entity_player.getEntityAction<BeaconShopAction>();
|
||||
if (beacon_shop_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop action : {nameof(BeaconShopAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ReqBeaconShopRegisterItem)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ReqBeaconShopRegisterItem;
|
||||
|
||||
if (request.ItemGuid == string.Empty ||
|
||||
request.BeaconGuid == string.Empty ||
|
||||
request.ItemAmount <= 0 ||
|
||||
request.SellingPrice <= 0)
|
||||
{
|
||||
err_msg = $"Invalid Request Argument !!! : ItemGuid : {request.ItemGuid}, BeaconGuid : {request.BeaconGuid}, ItemAmount : {request.ItemAmount}, SellingPrice : {request.SellingPrice}";
|
||||
result.setFail(ServerErrorCode.BeaconShopInvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_action.tryRegisterItemToBeaconShop(request.ItemGuid, (UInt16)request.ItemAmount, request.SellingPrice, request.BeaconGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(player, errorResult, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_SHOP_RETURN_ITEM), typeof(BeaconShopReturnItemPacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconShopReturnItemPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(Player player, Result result, string itemGuid = "", string beaconGuid = "", CommonResult? commonResult = null)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckBeaconShopReturnItem = new GS2C_ACK_BEACON_SHOP_RETURN_ITEM();
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ack_packet.Response.AckBeaconShopReturnItem.ItemGuid = itemGuid;
|
||||
ack_packet.Response.AckBeaconShopReturnItem.BeaconGuid = beaconGuid;
|
||||
ack_packet.Response.AckBeaconShopReturnItem.CommonResult = commonResult;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!" );
|
||||
|
||||
var beacon_shop_action = entity_player.getEntityAction<BeaconShopAction>();
|
||||
if (beacon_shop_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop action : {nameof(BeaconShopAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ReqBeaconShopReturnItem)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ReqBeaconShopReturnItem;
|
||||
|
||||
if (request.ItemGuid == string.Empty ||
|
||||
request.BeaconGuid == string.Empty)
|
||||
{
|
||||
err_msg = $"Invalid Request Argument !!! : ItemGuid : {request.ItemGuid}, BeaconGuid : {request.BeaconGuid}";
|
||||
result.setFail(ServerErrorCode.BeaconShopInvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_action.BeaconShopReturnItem(request.ItemGuid, request.BeaconGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_SHOP_SEARCH_ITEM), typeof(BeaconShopSearchItemPacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconShopSearchItemPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(Player player, Result result, List<BeaconShopMongoDoc>? beaconShopMongoDocs)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckBeaconShopSearchItem = new GS2C_ACK_BEACON_SHOP_SEARCH_ITEM();
|
||||
|
||||
if (result.isSuccess() && beaconShopMongoDocs != null)
|
||||
{
|
||||
ack_packet.Response.AckBeaconShopSearchItem.BeaconShopItemBoardInfos.AddRange(beaconShopMongoDocs.Select<BeaconShopMongoDoc, BeaconShopItemBoardInfo>(x => x.toBeaconShopItemMongoDataClient()).ToList());
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!" );
|
||||
|
||||
var beacon_shop_action = entity_player.getEntityAction<BeaconShopAction>();
|
||||
if (beacon_shop_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop action : {nameof(BeaconShopAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ReqBeaconShopSearchItem)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ReqBeaconShopSearchItem;
|
||||
|
||||
if (request.ItemMetaid == 0)
|
||||
{
|
||||
err_msg = $"Invalid Request Argument !!! : ItemMetaid : {request.ItemMetaid}";
|
||||
result.setFail(ServerErrorCode.BeaconShopInvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_action.BeaconShopSearchItem((META_ID)request.ItemMetaid);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(player, errorResult, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_SHOP_GET_SOLD_RECORDS), typeof(BeaconShopSoldRecordInfoPacketHandler), typeof(GameLoginListener))]
|
||||
public class BeaconShopSoldRecordInfoPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS(Player player, Result result, List<BeaconShopSoldRecord>? beaconShopSoldRecords, double totalGivenPrice = 0)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AckBeaconShopGetSoldRecords = new GS2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS();
|
||||
|
||||
if (result.isSuccess() && beaconShopSoldRecords != null)
|
||||
{
|
||||
ack_packet.Response.AckBeaconShopGetSoldRecords.BeaconShopSoldRecordInfos.AddRange(beaconShopSoldRecords.Select<BeaconShopSoldRecord, BeaconShopSoldRecordInfo>(x => x.toBeaconShopSoldRecordData4Client()).ToList());
|
||||
ack_packet.Response.AckBeaconShopGetSoldRecords.TotalGivenPrice = totalGivenPrice;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
|
||||
|
||||
var beacon_shop_action = entity_player.getEntityAction<BeaconShopAction>();
|
||||
if (beacon_shop_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get beacon shop action : {nameof(BeaconShopAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ReqBeaconShopGetSoldRecords)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ReqBeaconShopGetSoldRecords;
|
||||
|
||||
if (request.BeaconGuid == string.Empty)
|
||||
{
|
||||
err_msg = $"Invalid Request Argument !!! : BeaconGuid : {request.BeaconGuid}";
|
||||
result.setFail(ServerErrorCode.BeaconShopInvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await beacon_shop_action.BeaconShopGetSoldRecords(request.BeaconGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS(entity_player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS(player, errorResult, null);
|
||||
}
|
||||
}
|
||||
689
GameServer/Contents/Buff/Action/BuffAction.cs
Normal file
689
GameServer/Contents/Buff/Action/BuffAction.cs
Normal file
@@ -0,0 +1,689 @@
|
||||
using ServerCore;
|
||||
using ServerCommon;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
|
||||
public class BuffAction : EntityActionBase
|
||||
{
|
||||
private BuffCacheRequest? m_buff_cache_request = null;
|
||||
|
||||
public BuffAction(Player owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> loadBuff()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!!");
|
||||
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(buff_attribute, () => $"buff_attribute is null !!!");
|
||||
|
||||
m_buff_cache_request = new BuffCacheRequest(player, server_logic.getRedisConnector());
|
||||
result = await m_buff_cache_request.fetchBuff();
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var buff_cache = m_buff_cache_request.getBuffCache();
|
||||
if (buff_cache == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(buff_attribute, (new List<CacheBase>() { buff_cache }));
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var buff_channel in buff_attribute.BuffInfos)
|
||||
{
|
||||
foreach (var buff in buff_channel.Value)
|
||||
{
|
||||
changeAttribute(buff.Value.BuffMetaID, false);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public (Result result, BuffAttribute.BuffInfo? addBuff, BuffAttribute.BuffInfo? delBuff, BuffAttribute.BuffInfo? delStopBuff) UseEqipedBuff(META_ID buff_meta_id, int clientUIStep)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
BuffAttribute.BuffInfo? add_buff_attribute = null;
|
||||
BuffAttribute.BuffInfo? del_buff_attribute = null;
|
||||
BuffAttribute.BuffInfo? del_step_buff_attribute = null;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
if (!MetaData.Instance._BuffTable.TryGetValue((int)buff_meta_id, out var buffData))
|
||||
{
|
||||
err_msg = $"Not Exisxt BuffId : {buff_meta_id} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null, null);
|
||||
}
|
||||
|
||||
if (buffData.BuffCategory != MetaAssets.EBuffCategory.TOOL)
|
||||
{
|
||||
err_msg = $"BuffType is not TOOL : {buffData.BuffId} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffInvalidBuffCategoryType, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null, null);
|
||||
}
|
||||
|
||||
result = GetBuffFromAttribute(buffData.BuffCategory, buffData.BuffChannel, out var buff);
|
||||
if (result.isFail() || buff == null)
|
||||
{
|
||||
return (result, null, null, null);
|
||||
}
|
||||
|
||||
if (buff.BuffMetaID != buff_meta_id)
|
||||
{
|
||||
err_msg = $"Not Found Buff buff_meta_id : {buff_meta_id} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null, null);
|
||||
}
|
||||
|
||||
if (buffData.BuffEndCondition == EBuffEndCondition.ACTIONSTEP)
|
||||
{
|
||||
if (clientUIStep >= buffData.BuffEndConditionValue)
|
||||
{
|
||||
(result, del_step_buff_attribute) = DelBuffProcess(buff_meta_id);
|
||||
if (result.isFail())
|
||||
return (result, null, null, null);
|
||||
}
|
||||
|
||||
if (buffData.ActionBuffId != 0)
|
||||
{
|
||||
(result, add_buff_attribute, del_buff_attribute) = AddBuffProcess((META_ID)buffData.ActionBuffId);
|
||||
if (result.isFail())
|
||||
return (result, null, null, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(result, del_buff_attribute) = DelBuffProcess(buff_meta_id);
|
||||
if (result.isFail())
|
||||
return (result, null, null, null);
|
||||
}
|
||||
|
||||
return (result, add_buff_attribute, del_buff_attribute, del_step_buff_attribute);
|
||||
}
|
||||
|
||||
public Result GetBuffFromAttribute(EBuffCategory category, int channel, out BuffAttribute.BuffInfo? buff)
|
||||
{
|
||||
buff = null;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
if (buff_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get buff attribute : {nameof(BuffAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (buff_attribute.BuffInfos[category].TryGetValue(channel, out buff) == false)
|
||||
{
|
||||
err_msg = $"Failed to get buff. category : {category}, channel : {channel}";
|
||||
result.setFail(ServerErrorCode.BuffNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public (Result result, BuffAttribute.BuffInfo? add_buff_attribute, BuffAttribute.BuffInfo? del_buff_attribute) AddBuffProcess(META_ID buff_meta_id)
|
||||
{
|
||||
BuffAttribute.BuffInfo? add_buff_attribute = null;
|
||||
BuffAttribute.BuffInfo? del_buff_attribute = null;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
if (!MetaData.Instance._BuffTable.TryGetValue((int)buff_meta_id, out var buffData))
|
||||
{
|
||||
err_msg = $"Not found buffMeta !!! : buffMetaId:{buff_meta_id} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
if (buff_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get buff attribute : {nameof(BuffAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
var copy_buff_attribute = buff_attribute.onCloned() as BuffAttribute;
|
||||
NullReferenceCheckHelper.throwIfNull(copy_buff_attribute, () => $"copy_buff_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.BuffAdd);
|
||||
|
||||
//카테고리별 버프
|
||||
if (copy_buff_attribute.BuffInfos.TryGetValue(buffData.BuffCategory, out var buffchannelInfo) == false)
|
||||
{
|
||||
err_msg = $"Not Registry Buff Category !!! : buffMetaId:{buff_meta_id} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffNotRegistryCategory, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
//이미 동일한 채널의 버프가 있는경우
|
||||
if (buffchannelInfo.TryGetValue(buffData.BuffChannel, out var buffInfo) == true)
|
||||
{
|
||||
if (!MetaData.Instance._BuffTable.TryGetValue((int)buffInfo.BuffMetaID, out var curBuffData))
|
||||
{
|
||||
err_msg = $"Not found buffMeta !!! : buffMetaId:{buff_meta_id} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
//새로운것이 더 높거나 같으면 교체
|
||||
if (curBuffData.BuffPriority <= buffData.BuffPriority)
|
||||
{
|
||||
(result, del_buff_attribute) = DelBuff(buffData.BuffCategory, buffData.BuffChannel, ref invokers);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
(result, add_buff_attribute) = AddBuff(buffData, ref invokers);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
}
|
||||
return (result, add_buff_attribute, del_buff_attribute);
|
||||
}
|
||||
|
||||
string MaxBuffCategoty = "";
|
||||
switch (buffData.BuffCategory)
|
||||
{
|
||||
case MetaAssets.EBuffCategory.NORMAL: MaxBuffCategoty = "MaxNormalBuffNum"; break;
|
||||
case MetaAssets.EBuffCategory.INSTANCE: MaxBuffCategoty = "MaxInstanceBuffNum"; break;
|
||||
case MetaAssets.EBuffCategory.EVENT: MaxBuffCategoty = "MaxEventBuffNum"; break;
|
||||
case MetaAssets.EBuffCategory.TOOL: MaxBuffCategoty = "MaxToolBuffNum"; break;
|
||||
case MetaAssets.EBuffCategory.WEAR: MaxBuffCategoty = "MaxWearBuffNum"; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!MetaData.Instance._GameConfigMetaTable.TryGetValue(MaxBuffCategoty, out var strMaxBuffCount))
|
||||
{
|
||||
err_msg = $"Not found MaxBuffCategoty !!! : MaxBuffCategoty:{MaxBuffCategoty} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.GameConfigMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
if (false == strMaxBuffCount.toInt32(out var maxBuffCount))
|
||||
{
|
||||
err_msg = $"string to int parse failed. data : MaxBuffCount:{strMaxBuffCount} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.InvalidMetaData, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
DateTime? removeBuffStartTime = null;
|
||||
int removeBuffChannel = -1;
|
||||
|
||||
//최대 버퍼수량을 초과했을경우 가장 오래된 버프 제거
|
||||
if (buffchannelInfo.Count >= maxBuffCount)
|
||||
{
|
||||
foreach (var curBuffInfo in buffchannelInfo)
|
||||
{
|
||||
if (removeBuffStartTime == null || removeBuffStartTime > curBuffInfo.Value.BuffStartTime)
|
||||
{
|
||||
removeBuffStartTime = curBuffInfo.Value.BuffStartTime;
|
||||
removeBuffChannel = curBuffInfo.Key;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeBuffStartTime != null)
|
||||
{
|
||||
(result, del_buff_attribute) = DelBuff(buffData.BuffCategory, buffData.BuffChannel, ref invokers);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(result, add_buff_attribute) = AddBuff(buffData, ref invokers);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return (result, add_buff_attribute, del_buff_attribute);
|
||||
}
|
||||
|
||||
public (Result result, BuffAttribute.BuffInfo? del_buff_attribute) DelBuffProcess(META_ID buff_meta_id)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
if (!MetaData.Instance._BuffTable.TryGetValue((int)buff_meta_id, out var buffData))
|
||||
{
|
||||
err_msg = $"Not found buffMeta !!! : buffMetaId:{buff_meta_id} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.BuffDelete);
|
||||
|
||||
(result, var del_buff_attribute) = DelBuff(buffData.BuffCategory, buffData.BuffChannel, ref invokers);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return (result, del_buff_attribute);
|
||||
}
|
||||
|
||||
public async Task<Result> MoveServer(EPlaceType toMove)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
if (buff_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get buff attribute : {nameof(BuffAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
|
||||
var copy_buff_attribute = buff_attribute.onCloned() as BuffAttribute;
|
||||
NullReferenceCheckHelper.throwIfNull(copy_buff_attribute, () => $"copy_buff_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var delBuff = new List<BuffAttribute.BuffInfo>();
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.BuffDelete);
|
||||
|
||||
foreach (var ChannelBuff in copy_buff_attribute.BuffInfos)
|
||||
{
|
||||
foreach (var buff in ChannelBuff.Value)
|
||||
{
|
||||
if (!MetaData.Instance._BuffTable.TryGetValue((int)buff.Value.BuffMetaID, out var buffData))
|
||||
{
|
||||
err_msg = $"Not found ItemMeta !!! : buffMetaId:{buff.Value.BuffMetaID} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isRemainBuff(toMove, buffData) == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
delBuff.Add(buff.Value);
|
||||
ChannelBuff.Value.Remove(buff.Key);
|
||||
}
|
||||
}
|
||||
|
||||
result = await SaveBuffToCache(copy_buff_attribute);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var buff in delBuff)
|
||||
{
|
||||
changeAttribute(buff.BuffMetaID, true);
|
||||
|
||||
var task_log_data = BuffBusinessLogHelper.toLogInfo(buff, true);
|
||||
invokers.Add(new BuffBusinessLog(task_log_data));
|
||||
}
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF_LIST(player, delBuff);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<Result> SaveBuffToCache(BuffAttribute buff_attribute)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {toBasicString()}");
|
||||
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(m_buff_cache_request, () => $"m_buff_cache_request is null !!!");
|
||||
|
||||
var buff_cache = m_buff_cache_request.newBuffCache();
|
||||
NullReferenceCheckHelper.throwIfNull(buff_cache, () => $"buff_cache is null !!! - {toBasicString()}");
|
||||
|
||||
|
||||
result = await ServerBase.DataCopyHelper.copyCacheFromEntityAttributes(buff_cache, new List<EntityAttributeBase>() { buff_attribute });
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await m_buff_cache_request.UpsertBuff();
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void changeAttribute(META_ID buff_meta_id, bool isDelete)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (!MetaData.Instance._BuffTable.TryGetValue((int)buff_meta_id, out var buffData))
|
||||
{
|
||||
err_msg = $"Not found buffMeta !!! : buffMetaId:{buff_meta_id} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var buffAttribute in buffData.Traits)
|
||||
{
|
||||
if (buffAttribute.Operation == MetaAssets.ECVArithmeticOperation.Sub)
|
||||
{
|
||||
isDelete = isDelete == true ? false : true;
|
||||
}
|
||||
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!! - {toBasicString()}");
|
||||
|
||||
|
||||
var ability_action = owner.getEntityAction<AbilityAction>();
|
||||
if (ability_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get ability action : {nameof(AbilityAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (EnumHelper.tryParse<AttributeType>(buffAttribute.Attribute, out var attribute_enum) == false)
|
||||
{
|
||||
err_msg = $"Enum Pase Failed. AttributeType : {buffAttribute.Attribute}";
|
||||
result.setFail(ServerErrorCode.BuffInvalidAttributeType, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
ability_action.setAbility(attribute_enum, buffAttribute.Value, isDelete);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result> tryResetAttributeByBuff()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(buff_attribute, () => $"buff_attribute is null !!! - {toBasicString()}");
|
||||
|
||||
foreach (var buff_channel in buff_attribute.BuffInfos)
|
||||
{
|
||||
foreach (var buff in buff_channel.Value)
|
||||
{
|
||||
changeAttribute(buff.Value.BuffMetaID, false);
|
||||
}
|
||||
}
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
private bool isRemainBuff(EPlaceType toMove, MetaAssets.BuffMetaData buffData)
|
||||
{
|
||||
switch (toMove)
|
||||
{
|
||||
case EPlaceType.Concert: return buffData.IsConcertRemain;
|
||||
case EPlaceType.Meeting: return buffData.IsMeetingRemain;
|
||||
case EPlaceType.MyHome: return buffData.IsMyhomeRemain;
|
||||
case EPlaceType.Movie: return buffData.IsMovieRemain;
|
||||
case EPlaceType.World: return buffData.IsNormalRemain;
|
||||
case EPlaceType.BeaconCreateRoom: return buffData.is_beacon_remain;
|
||||
case EPlaceType.DressRoom: return buffData.is_dressroom_remain;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private (Result result, BuffAttribute.BuffInfo? add_buff_attribute) AddBuff(MetaAssets.BuffMetaData buffData, ref List<ILogInvoker> invokers)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
if (buff_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get buff attribute : {nameof(BuffAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (buff_attribute.AddBuff(buffData.BuffCategory, buffData.BuffChannel, buffData.BuffId, out var add_buff_attribute_info) == false)
|
||||
{
|
||||
err_msg = $"AddBuff failed !!! : buffMetaId:{buffData.BuffId} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null);
|
||||
}
|
||||
changeAttribute((META_ID)buffData.BuffId, false);
|
||||
|
||||
var task_log_data = BuffBusinessLogHelper.toLogInfo(add_buff_attribute_info, false);
|
||||
invokers.Add(new BuffBusinessLog(task_log_data));
|
||||
|
||||
return (result, add_buff_attribute_info);
|
||||
}
|
||||
|
||||
private (Result result, BuffAttribute.BuffInfo? del_buff_attribute) DelBuff(MetaAssets.EBuffCategory category, int channel, ref List<ILogInvoker> invokers)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {toBasicString()}");
|
||||
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
if (buff_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get buff attribute : {nameof(BuffAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (buff_attribute.RemoveBuff(category, channel, out var del_buff_attribute_info) == false)
|
||||
{
|
||||
err_msg = $"Failed Found Buff : BuffCategory:{category} channel:{channel} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuffNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null);
|
||||
}
|
||||
changeAttribute(del_buff_attribute_info.BuffMetaID, true);
|
||||
|
||||
var task_log_data = BuffBusinessLogHelper.toLogInfo(del_buff_attribute_info, true);
|
||||
invokers.Add(new BuffBusinessLog(task_log_data));
|
||||
|
||||
return (result, del_buff_attribute_info);
|
||||
}
|
||||
|
||||
public override async Task onTick()
|
||||
{
|
||||
updateBuff();
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Result updateBuff()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
try
|
||||
{
|
||||
var listDeleteChannel = new List<int>();
|
||||
var buff_attribute = player.getOriginEntityAttribute<BuffAttribute>();
|
||||
if (buff_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get buff attribute : {nameof(BuffAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
var copy_buff_attribute = buff_attribute.onCloned() as BuffAttribute;
|
||||
NullReferenceCheckHelper.throwIfNull(copy_buff_attribute, () => $"copy_buff_attribute is null !!!");
|
||||
|
||||
var it = copy_buff_attribute.BuffInfos.GetEnumerator();
|
||||
while (it.MoveNext() == true)
|
||||
{
|
||||
var buffDirectory = it.Current;
|
||||
var iter = buffDirectory.Value.GetEnumerator();
|
||||
|
||||
while (iter.MoveNext() == true)
|
||||
{
|
||||
var buff = iter.Current;
|
||||
|
||||
if (!MetaData.Instance._BuffTable.TryGetValue((int)buff.Value.BuffMetaID, out MetaAssets.BuffMetaData? buffData))
|
||||
{
|
||||
err_msg = $"Not found BuffMetaID : {buff.Value.BuffMetaID}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
if (buffData.BuffChannel != buff.Key)
|
||||
{
|
||||
err_msg = $"Not found BuffChannel : {buffData.BuffChannel}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
if (buffData.DurationTime == 0) // 무한
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DateTime endTime = buff.Value.BuffStartTime.AddSeconds(buffData.DurationTime);
|
||||
if (DateTime.UtcNow >= endTime)
|
||||
{
|
||||
(result, var del_buff_attribute) = DelBuffProcess((META_ID)buffData.BuffId);
|
||||
if (result.isFail()) continue;
|
||||
|
||||
Log.getLogger().debug($"DelBuff Ticker. buff meta id : {buffData.BuffId}");
|
||||
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(player, del_buff_attribute);
|
||||
|
||||
if (buffData.BuffEndExecutionType == EBuffEndExecution.GETBUFF)
|
||||
{
|
||||
int newBuffId = buffData.BuffEndExecutionValue;
|
||||
if (MetaData.Instance._BuffTable.TryGetValue(newBuffId, out MetaAssets.BuffMetaData? newData))
|
||||
{
|
||||
if (newData.BuffChannel != buffData.BuffChannel)
|
||||
{
|
||||
err_msg = $"Buff Channel newBuffId:{newBuffId} newData.BuffChannel:{newData.BuffChannel} data.BuffChannel:{buffData.BuffChannel} BuffMetaID:{buff.Value.BuffMetaID}";
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
continue;
|
||||
}
|
||||
|
||||
(result, var add_buff_attribute, del_buff_attribute) = AddBuffProcess((META_ID)newBuffId);
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(player, del_buff_attribute);
|
||||
BuffNotifyHelper.send_S2C_NTF_START_BUFF(player, add_buff_attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.getLogger().error(e.Message);
|
||||
result.setFail(ServerErrorCode.TryCatchException, err_msg);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
GameServer/Contents/Buff/BuffCheat.cs
Normal file
38
GameServer/Contents/Buff/BuffCheat.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
[ChatCommandAttribute("startbuff", typeof(ChatCommandStartBuff), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class ChatCommandStartBuff : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
Log.getLogger().info($"HandleStartBuff");
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Log.getLogger().error($"Invalid Argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uint.TryParse(args[0], out var buff_meta_id))
|
||||
{
|
||||
Log.getLogger().error($"questcomplete param parsing Error args : {args[0]}");
|
||||
return;
|
||||
}
|
||||
|
||||
var buff_action = player.getEntityAction<BuffAction>();
|
||||
(var result, var add_buff_attribute, var del_buff_attribute) = buff_action.AddBuffProcess(buff_meta_id);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed to AddBuffProcess() !!! : {result.toBasicString()} - {player.toBasicString()}");
|
||||
return;
|
||||
}
|
||||
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(player, del_buff_attribute);
|
||||
BuffNotifyHelper.send_S2C_NTF_START_BUFF(player, add_buff_attribute);
|
||||
}
|
||||
}
|
||||
38
GameServer/Contents/Buff/Helper/BuffHelper.cs
Normal file
38
GameServer/Contents/Buff/Helper/BuffHelper.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public static class BuffHelper
|
||||
{
|
||||
public static List<Buff> toBuffData4Client(this BuffAttribute buffAttribute)
|
||||
{
|
||||
var buff_list_4_client = new List<Buff>();
|
||||
|
||||
foreach (var buff_info in buffAttribute.BuffInfos)
|
||||
{
|
||||
foreach (var info in buff_info.Value)
|
||||
{
|
||||
Buff buff = new Buff();
|
||||
buff.BuffId = (Int32)info.Value.BuffMetaID;
|
||||
buff.BuffStartTime = info.Value.BuffStartTime.ToTimestamp();
|
||||
buff_list_4_client.Add(buff);
|
||||
}
|
||||
}
|
||||
|
||||
return buff_list_4_client;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
GameServer/Contents/Buff/Log/BuffBusinessLog.cs
Normal file
33
GameServer/Contents/Buff/Log/BuffBusinessLog.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class BuffBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private BuffLogData m_data_to_log;
|
||||
public BuffBusinessLog(BuffLogData log_data_param)
|
||||
: base(LogDomainType.Buff)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new BuffLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
25
GameServer/Contents/Buff/Log/BuffBusinessLogHelper.cs
Normal file
25
GameServer/Contents/Buff/Log/BuffBusinessLogHelper.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using ServerCommon;
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
static public class BuffBusinessLogHelper
|
||||
{
|
||||
static public BuffLogData toLogInfo(BuffAttribute.BuffInfo buffInfo, bool isDeleteBuff)
|
||||
{
|
||||
var logData = new BuffLogData();
|
||||
logData.setInfo(buffInfo, isDeleteBuff);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this BuffLogData logData, BuffAttribute.BuffInfo buffInfo, bool isDeleteBuff)
|
||||
{
|
||||
logData.BuffMetaID = buffInfo.BuffMetaID;
|
||||
logData.BuffStartTime = buffInfo.BuffStartTime;
|
||||
logData.BuffEndTime = DateTime.MinValue;
|
||||
|
||||
if (isDeleteBuff == true) logData.BuffEndTime = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
172
GameServer/Contents/Buff/PacketHandler/BuffNotifyHelper.cs
Normal file
172
GameServer/Contents/Buff/PacketHandler/BuffNotifyHelper.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using ServerCommon;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
using USER_GUID = System.String;
|
||||
using META_ID = System.UInt32;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public static class BuffNotifyHelper
|
||||
{
|
||||
public static bool send_S2C_NTF_START_BUFF(Player player, BuffAttribute.BuffInfo? buffAttributeInfo)
|
||||
{
|
||||
if (buffAttributeInfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var noti_packet = makeNotiStartBuffPacket(buffAttributeInfo, player.getUserGuid());
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
game_zone_action.broadcast(player, noti_packet);
|
||||
|
||||
QuestManager.It.QuestCheck(player, new QuestBuff(EQuestEventTargetType.BUFF, EQuestEventNameType.USED, (int)buffAttributeInfo.BuffMetaID)).Wait();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ClientToGame makeAckStartBuffPacket()
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
ack_packet.Response.ErrorCode = ServerErrorCode.Success;
|
||||
ack_packet.Response.StartBuffRes = new StartBuffRes();
|
||||
|
||||
return ack_packet;
|
||||
}
|
||||
|
||||
public static ClientToGame makeNotiStartBuffPacket(BuffAttribute.BuffInfo buffAttributeInfo, USER_GUID user_Guid)
|
||||
{
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.StartBuffNoti = new();
|
||||
noti_packet.Message.StartBuffNoti.ActorGuid = user_Guid;
|
||||
noti_packet.Message.StartBuffNoti.Buf = new();
|
||||
noti_packet.Message.StartBuffNoti.Buf.BuffId = (int)buffAttributeInfo.BuffMetaID;
|
||||
noti_packet.Message.StartBuffNoti.Buf.BuffStartTime = buffAttributeInfo.BuffStartTime.ToTimestamp();
|
||||
|
||||
return noti_packet;
|
||||
}
|
||||
|
||||
//이 패킷으로 stop모두 처리해도 되지 않을까
|
||||
public static bool send_S2C_NTF_DELETE_BUFF(Player player, BuffAttribute.BuffInfo? buffAttributeInfo)
|
||||
{
|
||||
if(buffAttributeInfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var noti_packet = makeNotiDeleteBuffPacket(buffAttributeInfo, player.getUserGuid());
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
game_zone_action.broadcast(player, noti_packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ClientToGame makeAckDeleteBuffPacket()
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
ack_packet.Response.ErrorCode = ServerErrorCode.Success;
|
||||
ack_packet.Response.StopBuffRes = new StopBuffRes();
|
||||
|
||||
return ack_packet;
|
||||
}
|
||||
|
||||
public static ClientToGame makeNotiDeleteBuffPacket(BuffAttribute.BuffInfo buffInfo, USER_GUID user_Guid)
|
||||
{
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.StopBuffNoti = new();
|
||||
|
||||
noti_packet.Message.StopBuffNoti.ActorGuid = user_Guid;
|
||||
|
||||
noti_packet.Message.StopBuffNoti.Buf = new();
|
||||
noti_packet.Message.StopBuffNoti.Buf.BuffId = (int)buffInfo.BuffMetaID;
|
||||
noti_packet.Message.StopBuffNoti.Buf.BuffStartTime = buffInfo.BuffStartTime.ToTimestamp();
|
||||
|
||||
return noti_packet;
|
||||
}
|
||||
|
||||
|
||||
public static bool send_S2C_NTF_DELETE_BUFF_LIST(Player player, List<BuffAttribute.BuffInfo>? buffAttributeInfo)
|
||||
{
|
||||
if (buffAttributeInfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new ();
|
||||
noti_packet.Message.DelBuffListNoti = new ();
|
||||
|
||||
foreach (var buff_attribute in buffAttributeInfo)
|
||||
{
|
||||
var buff_info = new Buff();
|
||||
buff_info.BuffId = (int)buff_attribute.BuffMetaID;
|
||||
buff_info.BuffStartTime = buff_attribute.BuffStartTime.ToTimestamp();
|
||||
noti_packet.Message.DelBuffListNoti.DelBuffList.Add(buff_info);
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, noti_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool send_S2C_NTF_USE_EQUIPED_BUFF(Player player, USER_GUID user_guid, META_ID buff_meta_id, int client_buff_step, int client_buff_random_state, Int64 client_buff_action_start_time)
|
||||
{
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.UseEquipedBuffNoti = new();
|
||||
|
||||
noti_packet.Message.UseEquipedBuffNoti.ActorGuid = user_guid;
|
||||
noti_packet.Message.UseEquipedBuffNoti.EquipedBuffId = (int)buff_meta_id;
|
||||
noti_packet.Message.UseEquipedBuffNoti.EquipedBuffStep = client_buff_step;
|
||||
noti_packet.Message.UseEquipedBuffNoti.EquipedBuffRandomState = client_buff_random_state;
|
||||
noti_packet.Message.UseEquipedBuffNoti.ActionStartTime = client_buff_action_start_time;
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, noti_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
game_zone_action.broadcast(player, noti_packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool send_S2C_NTF_LOGIN_BUFF(this Player player)
|
||||
{
|
||||
var buffAttribute = player.getEntityAttribute<BuffAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(buffAttribute, () => $"buffAttribute is null !!!");
|
||||
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.LoginBuffNoti = new();
|
||||
noti_packet.Message.LoginBuffNoti.BuffInfo = new();
|
||||
if(buffAttribute != null)
|
||||
{
|
||||
noti_packet.Message.LoginBuffNoti.BuffInfo.Buff.AddRange(buffAttribute.toBuffData4Client());
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, noti_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.StartBuffReq), typeof(StartBuffPacketHandler), typeof(GameLoginListener))]
|
||||
public class StartBuffPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_START_BUFF(Player player, Result result)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.StartBuffRes = new StartBuffRes();
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(game_msg, () => $"game_msg is null !!! - {player.toBasicString()}");
|
||||
var request = game_msg.Request.StartBuffReq;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
// 1. 캐릭터 선택 상태 체크
|
||||
var selected_character = player_action.getSelectedCharacter();
|
||||
if (null == selected_character)
|
||||
{
|
||||
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_START_BUFF(player, result);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
var buff_action = player.getEntityAction<BuffAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(buff_action, () => $"buff_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, var add_buff_attribute, var del_buff_attribute) = buff_action.AddBuffProcess((META_ID)request.BuffId);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to AddBuffProcess() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
send_S2C_ACK_START_BUFF(player, result);
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
send_S2C_ACK_START_BUFF(player, result);
|
||||
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(player, del_buff_attribute);
|
||||
BuffNotifyHelper.send_S2C_NTF_START_BUFF(player, add_buff_attribute);
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_START_BUFF(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.StopBuffReq), typeof(StopBuffPacketHandler), typeof(GameLoginListener))]
|
||||
public class StopBuffPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_STOP_BUFF(Player player, Result result)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.StopBuffRes = new StopBuffRes();
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
ArgumentNullException.ThrowIfNull(entity_player, $"entity_player is null !!!");
|
||||
|
||||
var buff_action = entity_player.getEntityAction<BuffAction>();
|
||||
if (buff_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get buff action : {nameof(BuffAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_STOP_BUFF(entity_player, result);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.StopBuffReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_STOP_BUFF(entity_player, result);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
var request = game_msg.Request.StopBuffReq;
|
||||
|
||||
(result, var del_buff_attribute) = buff_action.DelBuffProcess((META_ID)request.BuffId);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to DelBuffProcess() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
send_S2C_ACK_STOP_BUFF(entity_player, result);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
send_S2C_ACK_STOP_BUFF(entity_player, result);
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(entity_player, del_buff_attribute);
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_STOP_BUFF(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.UseEquipedBuffReq), typeof(UseEquipedBuffPacketHandler), typeof(GameLoginListener))]
|
||||
public class UseEquipedBuffPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_USE_EQUIPED_BUFF(Player player, Result result)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.UseEquipedBuffRes = new UseEquipedBuffRes();
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var player = entityWithSession as Player;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
var req_msg = recvMessage as ClientToGame;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(req_msg, () => $"req_msg is null !!! - {player.toBasicString()}");
|
||||
var request = req_msg.Request.UseEquipedBuffReq;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var buff_action = player.getEntityAction<BuffAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(buff_action, () => $"buff_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, var add_buff_attribute, var del_buff_attribute, var del_step_buff_attribute) = buff_action.UseEqipedBuff((META_ID)request.EquopedBuffId, request.EquipedBuffStep);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to UseEqipedBuff() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
send_S2C_ACK_USE_EQUIPED_BUFF(player, result);
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
send_S2C_ACK_USE_EQUIPED_BUFF(player, result);
|
||||
BuffNotifyHelper.send_S2C_NTF_USE_EQUIPED_BUFF(player, player.getUserGuid(), (META_ID)request.EquopedBuffId, request.EquipedBuffStep, request.EquipedBuffRandomState, request.ActionStartTime);
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(player, del_step_buff_attribute);
|
||||
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(player, del_buff_attribute);
|
||||
BuffNotifyHelper.send_S2C_NTF_START_BUFF(player, add_buff_attribute);
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_USE_EQUIPED_BUFF(player, errorResult);
|
||||
}
|
||||
}
|
||||
218
GameServer/Contents/Calium/Action/CaliumConverterAction.cs
Normal file
218
GameServer/Contents/Calium/Action/CaliumConverterAction.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CaliumConverterAction : EntityActionBase
|
||||
{
|
||||
public CaliumConverterAction(Player owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit() => await Task.FromResult(new Result());
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public async Task<(double calium, double currency)> calculationConvertCalium(Dictionary<int, int> useMaterials)
|
||||
{
|
||||
var total_fluxEtheron = 0.0;
|
||||
|
||||
// 1. 플럭스 에테론 변환 처리
|
||||
foreach (var material in useMaterials)
|
||||
{
|
||||
if (!MetaData.Instance._CaliumConverterMaterialTable.TryGetValue(material.Key, out var material_data)) continue;
|
||||
var fluxEtheron = material_data.Value * material.Value;
|
||||
|
||||
total_fluxEtheron = CaliumStorageHelper.AddDoubleByLong(total_fluxEtheron, fluxEtheron);
|
||||
}
|
||||
|
||||
// 2. calium 계산 : fluxEtheron * 기본 변환율 * 에너지 효율 / 소수점 버림 처리
|
||||
var calium_storage_entity = GameServerApp.getServerLogic().findGlobalEntity<CaliumStorageEntity>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_entity, () => $"calium_storage_entity is null !!! : {getOwner().toBasicString()}");
|
||||
|
||||
var calium_storage_action = calium_storage_entity.getEntityAction<CaliumStorageAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!! : {getOwner().toBasicString()}");
|
||||
var efficiency = await calium_storage_action.getCaliumConverterEfficiency();
|
||||
|
||||
var calium = total_fluxEtheron * (double)MetaHelper.GameConfigMeta.CaliumConverterConversionRate * efficiency;
|
||||
calium = CaliumStorageHelper.roundDownDefaultDigitsFromDouble(calium);
|
||||
|
||||
// 3. 요구 재화 계산 : 소수점 올림 처리
|
||||
var currency = total_fluxEtheron * (double)ServerCommon.MetaHelper.GameConfigMeta.CaliumConverterCommissionRate;
|
||||
currency = Math.Ceiling(currency);
|
||||
|
||||
return (calium, currency);
|
||||
}
|
||||
|
||||
public Result checkConvertConditions(Dictionary<int, int> useMaterials, double convertCalium, double currency)
|
||||
{
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
var calium_storage_entity = server_logic.findGlobalEntity<CaliumStorageEntity>();
|
||||
var calium_storage_action = calium_storage_entity?.getEntityAction<CaliumStorageAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!!");
|
||||
|
||||
|
||||
// 1. Calium 총량 체크
|
||||
var total_calium = calium_storage_action.getTotalCalium(CaliumStorageType.Converter);
|
||||
if (total_calium < 0)
|
||||
{
|
||||
err_msg = $"fail to convert calium!!! : loading calium - {checkConvertConditions}";
|
||||
result.setFail(ServerErrorCode.FailToLoadCalium, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (convertCalium > total_calium)
|
||||
{
|
||||
err_msg = $"fail to convert calium!!! : lack of total calium - calium[{convertCalium}] / total[{total_calium}]";
|
||||
result.setFail(ServerErrorCode.LackOfTotalCalium, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 1일 제한 용량 체크
|
||||
var user_calium_attribute = player.getEntityAttribute<CaliumAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_attribute, () => $"user_calium_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var daily_calium = CaliumStorageHelper.roundHalfUpDefaultDigitsFromDouble(user_calium_attribute.DailyCalium);
|
||||
if (convertCalium > daily_calium)
|
||||
{
|
||||
err_msg = $"fail to convert calium!!! : lack of daily calium - calium[{convertCalium}] / daily[{user_calium_attribute.DailyCalium}] / roundUp[{daily_calium}]";
|
||||
result.setFail(ServerErrorCode.LackOfDailyCalium, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 3. 재화 보유 체크
|
||||
if (! checkCurrencyForConvertCalium(currency))
|
||||
{
|
||||
err_msg = $"fail to convert calium!!! : lack of currency - currency[{currency}]";
|
||||
result.setFail(ServerErrorCode.LackOfCommissionCurrency, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 4. 아이템 보유 체크
|
||||
if (!checkItemForConvertCalium(useMaterials))
|
||||
{
|
||||
err_msg = $"fail to convert calium!!! : lack of meterial - useMaterials[{useMaterials}]";
|
||||
result.setFail(ServerErrorCode.LackOfCommissionMaterials, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool checkCurrencyForConvertCalium(double currency)
|
||||
{
|
||||
var money_attribute = getOwner().getEntityAttribute<MoneyAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(money_attribute, () => $"money_attribute is null !!!");
|
||||
|
||||
var owner_currency = MetaHelper.GameConfigMeta.CaliumConverterCommissionType switch
|
||||
{
|
||||
CurrencyType.Gold => money_attribute.Gold,
|
||||
CurrencyType.Sapphire => money_attribute.Sapphire,
|
||||
CurrencyType.Ruby => money_attribute.Ruby,
|
||||
_ => 0.0
|
||||
};
|
||||
|
||||
return currency <= owner_currency;
|
||||
}
|
||||
|
||||
private bool checkItemForConvertCalium(Dictionary<int, int> useMaterials)
|
||||
{
|
||||
foreach (var material in useMaterials)
|
||||
{
|
||||
var inventory_action = getOwner().getEntityAction<InventoryActionBase>();
|
||||
if (!MetaData.Instance._CaliumConverterMaterialTable.TryGetValue(material.Key, out var material_data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!!");
|
||||
|
||||
var own_count = inventory_action.getItemStackCountAllByMetaId((uint)material_data.ItemId);
|
||||
if (material.Value > own_count) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<(Result result, IEnumerable<GameServer.Item>? items)> deleteMaterials(Dictionary<int, int> useMaterials)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
var inventory_action = getOwner().getEntityAction<InventoryActionBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!!");
|
||||
|
||||
var items = new List<GameServer.Item>();
|
||||
|
||||
foreach (var material in useMaterials)
|
||||
{
|
||||
if (!MetaData.Instance._CaliumConverterMaterialTable.TryGetValue(material.Key, out var material_data))
|
||||
{
|
||||
err_msg = $"fail to convert calium !!! : invalid material slot id - input slotId[{material.Key}]";
|
||||
result.setFail(ServerErrorCode.InvalidMaterialSlotId, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
(result, var item) = await inventory_action.tryDeleteItemByMetaId((uint)material_data.ItemId, (ushort)material.Value);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"fail to convert calium !!! : lack of material count - input slotId[{material.Key}] / cout[{material.Value}]";
|
||||
result.setFail(ServerErrorCode.LackOfCommissionMaterials, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
items.AddRange(item);
|
||||
}
|
||||
|
||||
return (result, items);
|
||||
}
|
||||
|
||||
public async Task<Result> changeCurrency(double obtainCalium, CurrencyType currencyType, double spendCurrency)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var money_action = getOwner().getEntityAction<MoneyAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!!");
|
||||
|
||||
// 1. calium 획득
|
||||
result = await money_action.changeMoney(CurrencyType.Calium, obtainCalium, useCaliumEvent: false);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 2. 변환을 위한 재화 소모
|
||||
result = await money_action.changeMoney(currencyType, -1 * spendCurrency, useCaliumEvent: false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result changeDailyCalium(Player player, double calium)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
// 1. 개인 daily calium 수량 수정
|
||||
var user_calium_attribute = player.getEntityAttribute<CaliumAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_attribute, () => $"user_calium_attribute is null !!! - calium:{calium} / {player.toBasicString()}");
|
||||
|
||||
user_calium_attribute.DailyCalium -= calium;
|
||||
user_calium_attribute.modifiedEntityAttribute();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
69
GameServer/Contents/Calium/Action/CaliumExchangerAction.cs
Normal file
69
GameServer/Contents/Calium/Action/CaliumExchangerAction.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CaliumExchangerAction : EntityActionBase
|
||||
{
|
||||
private const double BaseExchangeValue = 0.01;
|
||||
|
||||
public CaliumExchangerAction(Player owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit() => await Task.FromResult(new Result());
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public async Task<double> calculationConvertCalium(double sapphire)
|
||||
{
|
||||
var calium = await CaliumStorageHelper.calculateCaliumFromSapphire(sapphire);
|
||||
if (calium < BaseExchangeValue) calium = 0;
|
||||
|
||||
return calium;
|
||||
}
|
||||
|
||||
public Result checkConvertConditions(double sapphire)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
// 1. 재화 보유 체크
|
||||
var money_attribute = getOwner().getEntityAttribute<MoneyAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(money_attribute, () => $"money_attribute is null !!!");
|
||||
|
||||
if (money_attribute.Sapphire < sapphire)
|
||||
{
|
||||
var err_msg = $"fail to convert calium!!! : lack of currency - currency[{sapphire}]";
|
||||
result.setFail(ServerErrorCode.LackOfCommissionCurrency, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> changeCurrency(double obtainCalium, CurrencyType currencyType, double spendCurrency)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var money_action = getOwner().getEntityAction<MoneyAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!!");
|
||||
|
||||
// 1. calium 획득
|
||||
result = await money_action.changeMoney(CurrencyType.Calium, obtainCalium, useCaliumEvent: false);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 2. 변환을 위한 재화 소모
|
||||
result = await money_action.changeMoney(currencyType, -1 * spendCurrency, useCaliumEvent: false);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
50
GameServer/Contents/Calium/CaliumExchangerCheat.cs
Normal file
50
GameServer/Contents/Calium/CaliumExchangerCheat.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace GameServer.Contents.Calium;
|
||||
|
||||
[ChatCommandAttribute("caliumexchanger", typeof(ChatCommandCaliumExchanger), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
public class ChatCommandCaliumExchanger : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"ChatCommandCaliumExchanger");
|
||||
|
||||
var message = new ClientToGame();
|
||||
message.Request = new ClientToGameReq();
|
||||
message.Request.ReqCaliumExchangerInfo = new();
|
||||
|
||||
var result = await GameServerApp.getServerLogic().onCallProtocolHandler(player, message);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"fail to run ChatCommandCaliumExchanger!! : {result.toBasicString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("exchangecalium", typeof(ChatCommandConvertExchangeCalium), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
public class ChatCommandConvertExchangeCalium : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"ChatCommandConvertExchangeCalium");
|
||||
|
||||
if (args.Length < 1 ||false == double.TryParse(args[0], out var sapphire))
|
||||
{
|
||||
var err_msg = $"Not enough argument !!! : argCount:{args.Length} == 1 - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
var message = new ClientToGame();
|
||||
message.Request = new ClientToGameReq();
|
||||
message.Request.ReqConvertExchangerCalium = new();
|
||||
message.Request.ReqConvertExchangerCalium.Sapphire = sapphire;
|
||||
|
||||
var result = await GameServerApp.getServerLogic().onCallProtocolHandler(player, message);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"fail to run ChatCommandConvertExchangeCalium!! : {result.toBasicString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_CONVERT_EXCHANGER_CALIUM), typeof(ConvertExchangerCaliumPacketHandler), typeof(GameLoginListener))]
|
||||
public class ConvertExchangerCaliumPacketHandler : PacketRecvHandler
|
||||
{
|
||||
private async Task send_S2C_ACK_CONVERT_EXCHANGER_CALIUM(Player owner, Result result)
|
||||
{
|
||||
var ack_packet = new ClientToGame
|
||||
{
|
||||
Response = new ClientToGameRes
|
||||
{
|
||||
ErrorCode = result.ErrorCode,
|
||||
AckConvertExchangerCalium = new ()
|
||||
}
|
||||
};
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
var account_attribute = owner.getOriginEntityAttribute<AccountAttribute>();
|
||||
var level_attribute = owner.getOriginEntityAttribute<LevelAttribute>();
|
||||
var money_attribute = owner.getOriginEntityAttribute<MoneyAttribute>();
|
||||
var nickname_attribute = owner.getOriginEntityAttribute<NicknameAttribute>();
|
||||
|
||||
var char_info = new CharInfo
|
||||
{
|
||||
Level = (int)level_attribute!.Level,
|
||||
Exp = (int)level_attribute.Exp,
|
||||
|
||||
Gold = money_attribute!.Gold,
|
||||
Sapphire = money_attribute.Sapphire,
|
||||
Calium = money_attribute.Calium,
|
||||
Ruby = money_attribute.Ruby,
|
||||
|
||||
Usergroup = account_attribute!.AuthAdminLevelType.ToString(),
|
||||
Operator = (int)account_attribute.AuthAdminLevelType,
|
||||
|
||||
DisplayName = nickname_attribute!.Nickname,
|
||||
LanguageInfo = (int)account_attribute.LanguageType,
|
||||
|
||||
IsIntroComplete = 1
|
||||
};
|
||||
|
||||
ack_packet.Response.AckConvertExchangerCalium.CurrencyInfo = char_info;
|
||||
}
|
||||
|
||||
GameServerApp.getServerLogic().onSendPacket(owner, ack_packet);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
// 1. 기본 정보 체크
|
||||
var request = (recvMessage as ClientToGame)?.Request.ReqConvertExchangerCalium;
|
||||
if (null == request)
|
||||
{
|
||||
err_msg = $"Failed to get request type !!! : {nameof(ClientToGame.Request.ReqConvertExchangerCalium)}";
|
||||
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
await send_S2C_ACK_CONVERT_EXCHANGER_CALIUM(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 변환 로직 시행
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents,
|
||||
"CaliumConverterConvertSapphireToCalium", convertSapphireToCaliumDelegate);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
await send_S2C_ACK_CONVERT_EXCHANGER_CALIUM(player, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
async Task<Result> convertSapphireToCaliumDelegate() => await convertSapphireToCalium(player, request.Sapphire);
|
||||
}
|
||||
|
||||
private async Task<Result> convertSapphireToCalium(Player player, double sapphire)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var user_calium_exchager_action = player.getEntityAction<CaliumExchangerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_exchager_action, () => $"user_calium_exchager_action is null !!!");
|
||||
|
||||
var calium_storage_entity = GameServerApp.getServerLogic().findGlobalEntity<CaliumStorageEntity>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_entity, () => $"calium_storage_entity is null !!! - {player.toBasicString()}");
|
||||
var calium_storage_action = calium_storage_entity.getEntityAction<CaliumStorageAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
// 0. calium storage 체크
|
||||
result = await calium_storage_action.enableCaliumStorage();
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 1. Convert 수량 계산
|
||||
var calium = await user_calium_exchager_action.calculationConvertCalium(sapphire);
|
||||
if (calium <= 0)
|
||||
{
|
||||
var err_msg = $"failed to convert calium !!! - lack of convert calium:[{calium}] / {player.toBasicString()}]";
|
||||
result.setFail(ServerErrorCode.LackOfConvertCalium, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. Convert 조건 체크
|
||||
result = user_calium_exchager_action.checkConvertConditions(sapphire);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 3. 재화 변경
|
||||
result = await user_calium_exchager_action.changeCurrency(calium, CurrencyType.Sapphire, sapphire);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 4. DB 갱신 - player
|
||||
{
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.ConvertExchangeCalium, GameServerApp.getServerLogic().getDynamoDbClient(), true);
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail()) return result;
|
||||
}
|
||||
|
||||
// 5. 변경사항 전송
|
||||
var calium_event_action = calium_storage_entity.getEntityAction<CaliumEventAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_event_action, () => $"calium_event_action is null !!! - {player.toBasicString()}");
|
||||
var send = await calium_event_action.sendCaliumEventFromPlayer(player, CaliumEventType.calium_get, "교환소 교환", -1 * sapphire, calium, false);
|
||||
|
||||
// 6. 실패시 재화 롤백
|
||||
if (false == send.is_success)
|
||||
{
|
||||
result = await rollbackCurrency(player, calium, sapphire, send.event_data);
|
||||
|
||||
// 6-1. 롤백 성공시 패킷 실패 처리
|
||||
if (result.isSuccess())
|
||||
{
|
||||
var err_msg = $"failed to send echoSystem: sapphire[{sapphire}] / {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.FailToSendEchoSystem, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 6-2. 롤백 실패시 변경사항 전송 재시도 ( 패킷 성공 처리 )
|
||||
_ = await calium_event_action.sendCaliumEventFromPlayer(player, CaliumEventType.calium_get, "교환소 교환", -1 * sapphire, calium);
|
||||
}
|
||||
|
||||
// 7. Response 응답
|
||||
await send_S2C_ACK_CONVERT_EXCHANGER_CALIUM(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<Result> rollbackCurrency(Player player, double calium, double sapphire, CaliumEventData eventData)
|
||||
{
|
||||
var user_calium_exchanger_action = player.getEntityAction<CaliumExchangerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_exchanger_action, () => $"user_calium_exchanger_action is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 재화 변경
|
||||
result = await user_calium_exchanger_action.changeCurrency(-1 * calium, CurrencyType.Sapphire, -1 * sapphire);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 2. DB 갱신
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.ConvertExchangeCalium,
|
||||
GameServerApp.getServerLogic().getDynamoDbClient(), true);
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail()) return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"failed to rollback currency !!! - calium[{calium}] sapphire[{sapphire}] / {e} / {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.FailToSendEchoSystem, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_CONVERT_MATERIAL_TO_CALIUM), typeof(ConvertMaterialToCaliumPacketHandler), typeof(GameLoginListener))]
|
||||
public class ConvertMaterialToCaliumPacketHandler : PacketRecvHandler
|
||||
{
|
||||
private async Task send_S2C_ACK_CONVERT_MATERIAL_TO_CALIUM(Player owner, Result result, double totalCalium, float caliumForUser, List<Item>? items)
|
||||
{
|
||||
var ack_packet = new ClientToGame
|
||||
{
|
||||
Response = new ClientToGameRes
|
||||
{
|
||||
ErrorCode = result.ErrorCode,
|
||||
AckConvertMaterialToCalium = new()
|
||||
}
|
||||
};
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ack_packet.Response.AckConvertMaterialToCalium.TotalCalium = totalCalium;
|
||||
ack_packet.Response.AckConvertMaterialToCalium.CaliumForUser = caliumForUser;
|
||||
|
||||
if (null != items)
|
||||
{
|
||||
ack_packet.Response.AckConvertMaterialToCalium.DelItem.AddRange(items.Select(item => item.toItemData4Client()));
|
||||
}
|
||||
|
||||
// char info 획득
|
||||
var account_attribute = owner.getOriginEntityAttribute<AccountAttribute>();
|
||||
var level_attribute = owner.getOriginEntityAttribute<LevelAttribute>();
|
||||
var money_attribute = owner.getOriginEntityAttribute<MoneyAttribute>();
|
||||
var nickname_attribute = owner.getOriginEntityAttribute<NicknameAttribute>();
|
||||
|
||||
var char_info = new CharInfo
|
||||
{
|
||||
Level = (int)level_attribute!.Level,
|
||||
Exp = (int)level_attribute.Exp,
|
||||
|
||||
Gold = money_attribute!.Gold,
|
||||
Sapphire = money_attribute.Sapphire,
|
||||
Calium = money_attribute.Calium,
|
||||
Ruby = money_attribute.Ruby,
|
||||
|
||||
Usergroup = account_attribute!.AuthAdminLevelType.ToString(),
|
||||
Operator = (int)account_attribute.AuthAdminLevelType,
|
||||
|
||||
DisplayName = nickname_attribute!.Nickname,
|
||||
LanguageInfo = (int)account_attribute.LanguageType,
|
||||
|
||||
IsIntroComplete = 1
|
||||
};
|
||||
|
||||
ack_packet.Response.AckConvertMaterialToCalium.CurrencyInfo = char_info;
|
||||
}
|
||||
|
||||
GameServerApp.getServerLogic().onSendPacket(owner, ack_packet);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
|
||||
// 1. 기본 정보 체크
|
||||
var request = (recvMessage as ClientToGame)?.Request.ReqConvertMaterialToCalium;
|
||||
if (null == request)
|
||||
{
|
||||
err_msg = $"Failed to get request type !!! : {nameof(ClientToGame.Request.ReqConvertMaterialToCalium)}";
|
||||
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
await send_S2C_ACK_CONVERT_MATERIAL_TO_CALIUM(player, result, -1, -1, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 변환 로직 시행
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CaliumConverterConvertMaterialToCalium", convertMaterialToCaliumDelegate);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
await send_S2C_ACK_CONVERT_MATERIAL_TO_CALIUM(player, result, -1, -1, null);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
async Task<Result> convertMaterialToCaliumDelegate() => await convertMaterialToCalium(player, request.UseMaterials.ToDictionary());
|
||||
}
|
||||
|
||||
private async Task<Result> convertMaterialToCalium(Player player, Dictionary<int, int> useMaterials)
|
||||
{
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var result = new Result();
|
||||
|
||||
var user_calium_action = player.getEntityAction<CaliumConverterAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_action, () => $"action is null !!!");
|
||||
|
||||
var calium_storage_entity = GameServerApp.getServerLogic().findGlobalEntity<CaliumStorageEntity>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_entity, () => $"caliuim_storage_entity is null !!! - {player.toBasicString()}");
|
||||
var calium_storage_action = calium_storage_entity.getEntityAction<CaliumStorageAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
// 0. calium storage 체크
|
||||
result = await calium_storage_action.enableCaliumStorage();
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 1. Convert 수량 계산
|
||||
var convert = await user_calium_action.calculationConvertCalium(useMaterials);
|
||||
|
||||
// 2. Convert 조건 체크
|
||||
result = user_calium_action.checkConvertConditions(useMaterials, convert.calium, convert.currency);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 3. Item 제거
|
||||
var delete_materials = await user_calium_action.deleteMaterials(useMaterials);
|
||||
if (delete_materials.result.isFail()) return delete_materials.result;
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(delete_materials.items, () => $"delete_materials.items is null !!!");
|
||||
|
||||
// 4. 재화 변경
|
||||
result = await user_calium_action.changeCurrency(convert.calium, MetaHelper.GameConfigMeta.CaliumConverterCommissionType, convert.currency);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
// 5. 개인 calium converter 정보 수정
|
||||
result = user_calium_action.changeDailyCalium(player, convert.calium);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var delta = -1 * convert.calium;
|
||||
var total_calium = CaliumStorageHelper.AddDoubleByLong(calium_storage_action.getTotalCalium(CaliumStorageType.Converter), delta);
|
||||
|
||||
// 6. DB 갱신
|
||||
{
|
||||
var batch = new QueryBatchEx<QueryRunnerWithItemRequest>(player, LogActionType.ConvertCalium, GameServerApp.getServerLogic().getDynamoDbClient(), true);
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
batch.addQuery(new DBQStorageCaliumUpdate(CaliumStorageType.Converter, delta));
|
||||
|
||||
writeBusinessLog(player, batch, total_calium, convert.calium);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail()) return result;
|
||||
}
|
||||
|
||||
// 7. Calium Storage 재로딩
|
||||
_ = await calium_storage_action.loadStorageAttribute();
|
||||
|
||||
// 8. 변경사항 전송
|
||||
var calium_event_action = calium_storage_entity.getEntityAction<CaliumEventAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_event_action, () => $"calium_event_action is null !!! - {player.toBasicString()}");
|
||||
await calium_event_action.sendCaliumEventFromPlayer(player, CaliumEventType.extra_get, "컨버터 교환", -1 * convert.currency, 0);
|
||||
|
||||
// 9. Response 응답
|
||||
var user_calium_attribute = player.getEntityAttribute<CaliumAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_attribute, () => $"user_calium_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
await send_S2C_ACK_CONVERT_MATERIAL_TO_CALIUM(player, result, total_calium, (float)user_calium_attribute.DailyCalium, delete_materials.items.ToList());
|
||||
|
||||
// 10. 정보 변경 통보
|
||||
calium_storage_action.sendChangeStorageInfo();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void writeBusinessLog(Player player, QueryBatchBase queryBatchBase, double converterTotalCalium, double obtainCalium)
|
||||
{
|
||||
var user_calium_attribute = player.getEntityAttribute<CaliumAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_attribute, () => $"CaliumAttribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
// Converter Calium 변화량 기록
|
||||
var calium_log_data = new CaliumConverterLogData();
|
||||
calium_log_data.CurrentDailyCalium = user_calium_attribute.DailyCalium;
|
||||
calium_log_data.CurrentTotalCalium = converterTotalCalium;
|
||||
calium_log_data.DeltaDailyCalium = obtainCalium;
|
||||
calium_log_data.DeltaTotalCalium = obtainCalium;
|
||||
calium_log_data.AmountDeltaType = AmountDeltaType.Consume;
|
||||
|
||||
var calium_business_log = new CaliumBusinessLog(calium_log_data);
|
||||
queryBatchBase.appendBusinessLog(calium_business_log);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_CALIUM_CONVERTER), typeof(GetCaliumConverterInfoPacketHandler), typeof(GameLoginListener))]
|
||||
public class GetCaliumConverterInfoPacketHandler : PacketRecvHandler
|
||||
{
|
||||
private static void send_S2C_ACK_CALIUM_CONVERTER(Player owner, Result result, double calium, float caliumForUser, float caliumEfficiency)
|
||||
{
|
||||
var ack_packet = new ClientToGame
|
||||
{
|
||||
Response = new ClientToGameRes
|
||||
{
|
||||
ErrorCode = result.ErrorCode,
|
||||
AckCaliumConverter = new()
|
||||
}
|
||||
};
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ack_packet.Response.AckCaliumConverter.Calium = calium;
|
||||
ack_packet.Response.AckCaliumConverter.CaliumEfficiency = caliumEfficiency;
|
||||
ack_packet.Response.AckCaliumConverter.CaliumForUser = caliumForUser;
|
||||
}
|
||||
|
||||
GameServerApp.getServerLogic().onSendPacket(owner, ack_packet);
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => "player is null !!!");
|
||||
|
||||
// 1. 기본 정보 체크
|
||||
var request = (recvMessage as ClientToGame)?.Request.ReqCaliumConverter;
|
||||
if (null == request)
|
||||
{
|
||||
err_msg = $"Failed to get request type !!! : {nameof(ClientToGame.Request.ReqCaliumConverter)}";
|
||||
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_CALIUM_CONVERTER(player, result, 0, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "GetCaliumConverterInfo", getCaliumConverterInfoDelegase);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_CALIUM_CONVERTER(player, result, 0, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 총 칼리움 잔여량 체크
|
||||
var calium_converter = GameServerApp.getServerLogic().findGlobalEntity<CaliumStorageEntity>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_converter, () => $"calium converter is null !!!");
|
||||
|
||||
var calium_storage_action = calium_converter.getEntityAction<CaliumStorageAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!! - {calium_converter.toBasicString()}");
|
||||
|
||||
var calium = calium_storage_action.getTotalCalium(CaliumStorageType.Converter);
|
||||
if (calium < 0)
|
||||
{
|
||||
err_msg = $"Failed to load calium !!! : {nameof(calium_storage_action.getTotalCalium)}";
|
||||
result.setFail(ServerErrorCode.FailToLoadCalium, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_CALIUM_CONVERTER(player, result, 0, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 3. 변환 에너지 효율 체크
|
||||
var calium_efficiency = await calium_storage_action.getCaliumConverterEfficiency();
|
||||
|
||||
// 4. 일일 제공 잔여량 체크
|
||||
var user_calium_attribute = player.getEntityAttribute<CaliumAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_calium_attribute, () => $"user_calium_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_CALIUM_CONVERTER(player, result, calium, (float)user_calium_attribute.DailyCalium, (float)calium_efficiency);
|
||||
|
||||
return result;
|
||||
|
||||
async Task<Result> getCaliumConverterInfoDelegase() => await getCaliumConverterInfoAsync(player);
|
||||
}
|
||||
|
||||
private async Task<Result> getCaliumConverterInfoAsync(Player player)
|
||||
{
|
||||
var result = new Result();
|
||||
var current_pivot_date = CaliumStorageHelper.CurrentPivotTimeDate();
|
||||
var is_create = false;
|
||||
|
||||
// 1. attribute 가져오기
|
||||
var attribute = player.getEntityAttribute<CaliumAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(attribute, () => $"CaliumAttribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
// 2. origin doc 이 없으면 신규 생성 처리
|
||||
var origin_doc = attribute.getOriginDocBase<CaliumAttribute>();
|
||||
if (null == origin_doc)
|
||||
{
|
||||
var new_doc = new CaliumDoc(player.getUserGuid());
|
||||
var attrib = new_doc.getAttrib<CaliumAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(attrib, () => $"CaliumAttrib is null !!! - {player.toBasicString()}");
|
||||
|
||||
attrib.DailyCalium = (double)MetaHelper.GameConfigMeta.CaliumConverterLimitPerPerson;
|
||||
attrib.ProvidedDate = current_pivot_date;
|
||||
|
||||
attribute.copyEntityAttributeFromDoc(new_doc);
|
||||
attribute.newEntityAttribute();
|
||||
is_create = true;
|
||||
}
|
||||
|
||||
// 3. 일일 지급 갱신 주기 체크
|
||||
if (null != origin_doc && attribute.ProvidedDate >= current_pivot_date)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (false == is_create)
|
||||
{
|
||||
attribute.DailyCalium = (double)MetaHelper.GameConfigMeta.CaliumConverterLimitPerPerson;
|
||||
attribute.ProvidedDate = current_pivot_date;
|
||||
attribute.modifiedEntityAttribute();
|
||||
}
|
||||
|
||||
// 4. db 갱신
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.ChangeConvertCaliumInfo, GameServerApp.getServerLogic().getDynamoDbClient(), true);
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
batch.addQuery(new QueryFinal());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_CALIUM_EXCHANGER_INFO), typeof(GetCaliumExchangerInfoPacketHandler), typeof(GameLoginListener))]
|
||||
public class GetCaliumExchangerInfoPacketHandler : PacketRecvHandler
|
||||
{
|
||||
private async Task send_S2C_ACK_CALIUM_EXCHANGER_INFO(Player owner, Result result, double inflationRate, DateTime nextEpochTime)
|
||||
{
|
||||
var ack_packet = new ClientToGame
|
||||
{
|
||||
Response = new ClientToGameRes
|
||||
{
|
||||
ErrorCode = result.ErrorCode,
|
||||
AckCaliumExchangerInfo = new ()
|
||||
}
|
||||
};
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
ack_packet.Response.AckCaliumExchangerInfo.InflationRate = inflationRate;
|
||||
ack_packet.Response.AckCaliumExchangerInfo.FixedExchangeRate = CaliumStorageHelper.FixedExchangeRate;
|
||||
|
||||
var time = new DateTime(nextEpochTime.Year, nextEpochTime.Month, nextEpochTime.Day, nextEpochTime.Hour, nextEpochTime.Minute, nextEpochTime.Second, DateTimeKind.Utc);
|
||||
ack_packet.Response.AckCaliumExchangerInfo.NextEpochTime = time.ToTimestamp();
|
||||
}
|
||||
|
||||
GameServerApp.getServerLogic().onSendPacket(owner, ack_packet);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
// 1. 기본 정보 체크
|
||||
var request = (recvMessage as ClientToGame)?.Request.ReqCaliumExchangerInfo;
|
||||
if (null == request)
|
||||
{
|
||||
err_msg = $"Failed to get request type !!! : {nameof(ClientToGame.Request.ReqCaliumExchangerInfo)}";
|
||||
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
await send_S2C_ACK_CALIUM_EXCHANGER_INFO(player, result, 0, DateTimeHelper.MinTime);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 정보 조회
|
||||
var calium_storage_entity = GameServerApp.getServerLogic().findGlobalEntity<CaliumStorageEntity>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_entity, () => $"calium_storage_entity is null !!! - {player.toBasicString()}");
|
||||
|
||||
var calium_storage_action = calium_storage_entity.getEntityAction<CaliumStorageAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!! - {calium_storage_entity.toBasicString()} / {player.toBasicString()}");
|
||||
|
||||
var info = await calium_storage_action.getCaliumStorageInfo();
|
||||
await send_S2C_ACK_CALIUM_EXCHANGER_INFO(player, result, info.DailyInflationRate, info.DailyPivotDate.AddDays(1));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
541
GameServer/Contents/Cart/Action/CartAction.cs
Normal file
541
GameServer/Contents/Cart/Action/CartAction.cs
Normal file
@@ -0,0 +1,541 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
using GameServer.PacketHandler;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CartAction : EntityActionBase
|
||||
{
|
||||
private Cart? m_Cart = null;
|
||||
|
||||
public CartAction(Player owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
m_Cart = new(player);
|
||||
await m_Cart.onInit();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(m_Cart, () => $"m_Cart is null !!!");
|
||||
m_Cart.onCearAll();
|
||||
}
|
||||
|
||||
public Result AddCartFromDoc(CartDoc? cartDoc)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (cartDoc == null) return result;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(m_Cart, () => $"m_Cart is null !!!");
|
||||
var cart_attribute = m_Cart.getEntityAttribute<CartAttribute>();
|
||||
if (cart_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get cart attribute : {nameof(CartAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(cart_attribute.copyEntityAttributeFromDoc(cartDoc) == false)
|
||||
{
|
||||
err_msg = $"Failed copyEntityAttributeFromDoc !!! - {typeof(CartAction).Name}";
|
||||
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result GetCart4Client()
|
||||
{
|
||||
var result = new Result();
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
GetCartPacketHandler.send_S2C_ACK_GET_CART(player, result, m_Cart);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> AddCartProcess(META_ID item_meta_id, int count, CurrencyType currency_type)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!!");
|
||||
|
||||
var fn_add_cart = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
|
||||
(result, int item_sum_count) = AddCart(item_meta_id, count, currency_type);
|
||||
if (result.isFail())
|
||||
{
|
||||
PacketHandler.AddCartPacketHandler.send_S2C_ACK_ADD_CART(player, result, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<(META_ID, int)> deltaCartList = new List<(META_ID, int)>() { (item_meta_id, count) };
|
||||
var task_log_data = CartBusinessLogHelper.toLogInfo(deltaCartList);
|
||||
invokers.Add(new CartBusinessLog(task_log_data));
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CartAdd
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
AddCartPacketHandler.send_S2C_ACK_ADD_CART(player, result, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
AddCartPacketHandler.send_S2C_ACK_ADD_CART(player, result, item_meta_id, item_sum_count);
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "AddCart", fn_add_cart);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> DeleteCartProcess(List<CartItemInfo> req_del_cart_items)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!!");
|
||||
|
||||
var fn_delete_cart = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
|
||||
(result, var isRemoveItem) = DeleteCart(req_del_cart_items);
|
||||
if (result.isFail())
|
||||
{
|
||||
DelCartPacketHandler.send_S2C_ACK_DEL_CART(player, result, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<(META_ID, int)> deltaCartList = req_del_cart_items.Select(x => ((META_ID)x.ItemId, x.Count)).ToList();
|
||||
var task_log_data = CartBusinessLogHelper.toLogInfo(deltaCartList);
|
||||
invokers.Add(new CartBusinessLog(task_log_data));
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CartDelete
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
DelCartPacketHandler.send_S2C_ACK_DEL_CART(player, result, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
DelCartPacketHandler.send_S2C_ACK_DEL_CART(player, result, isRemoveItem);
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "DeleteCart", fn_delete_cart);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> BuyCartProcess(List<CartItemInfo> req_buy_cart_items)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
if (req_buy_cart_items.Count == 0)
|
||||
{
|
||||
BuyCartPacketHandler.send_S2C_ACK_BUY_CART(player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var fn_buy_cart = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
|
||||
// 카트에서 제거
|
||||
var deleteResult = DeleteCart(req_buy_cart_items);
|
||||
if (deleteResult.result.isFail())
|
||||
{
|
||||
BuyCartPacketHandler.send_S2C_ACK_BUY_CART(player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<(META_ID, int)> deltaCartList = req_buy_cart_items.Select(x => ((META_ID)x.ItemId, x.Count)).ToList();
|
||||
var task_log_data = CartBusinessLogHelper.toLogInfo(deltaCartList);
|
||||
invokers.Add(new CartBusinessLog(task_log_data));
|
||||
|
||||
// 재화 차감
|
||||
result = await PayCurrencyForItem(req_buy_cart_items);
|
||||
if (result.isFail())
|
||||
{
|
||||
BuyCartPacketHandler.send_S2C_ACK_BUY_CART(player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 아이템 지급
|
||||
var takeItemResult = await TakeCartItem(req_buy_cart_items);
|
||||
if (takeItemResult.result.isFail())
|
||||
{
|
||||
BuyCartPacketHandler.send_S2C_ACK_BUY_CART(player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await updateItemFirstPurchaseHistory(req_buy_cart_items);
|
||||
if (result.isFail())
|
||||
{
|
||||
BuyCartPacketHandler.send_S2C_ACK_BUY_CART(player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CartPurchase
|
||||
, server_logic.getDynamoDbClient(), true);
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
BuyCartPacketHandler.send_S2C_ACK_BUY_CART(player, result, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
BuyCartPacketHandler.send_S2C_ACK_BUY_CART(player, result, takeItemResult.changed_Items);
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "BuyCart", fn_buy_cart);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private (Result result, Int32 item_sum_count) AddCart(META_ID item_meta_id, int count, CurrencyType currency_type)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
NullReferenceCheckHelper.throwIfNull(m_Cart, () => $"m_Cart is null !!!");
|
||||
var cart_attribute = m_Cart.getEntityAttribute<CartAttribute>();
|
||||
if (cart_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get cart attribute : {nameof(CartAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
cart_attribute.CartItems.TryGetValue(currency_type, out var category_cart_items);
|
||||
NullReferenceCheckHelper.throwIfNull(category_cart_items, () => $"category_cart_items is null !!!");
|
||||
|
||||
if (category_cart_items.Count >= 20)
|
||||
{
|
||||
err_msg = $"cart is Full. currency_type : {currency_type}";
|
||||
result.setFail(ServerErrorCode.CartMaxCountExceed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
int sum_count = count;
|
||||
if (category_cart_items.TryGetValue(item_meta_id, out var cur_count) == false)
|
||||
{
|
||||
category_cart_items.TryAdd(item_meta_id, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
sum_count += cur_count;
|
||||
category_cart_items[item_meta_id] = sum_count;
|
||||
}
|
||||
|
||||
var player = m_Cart.getRootParent() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
result = player.checkItemFirstPurchaseItemCount((int)item_meta_id, sum_count);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
if (sum_count > 99)
|
||||
{
|
||||
err_msg = $"FullStack of this item in cart. itemId : {item_meta_id}";
|
||||
result.setFail(ServerErrorCode.CartStackCountInvalid, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
cart_attribute.modifiedEntityAttribute();
|
||||
|
||||
return (result, sum_count);
|
||||
}
|
||||
|
||||
private (Result result, bool isRemovedItem) DeleteCart(List<CartItemInfo> del_cart_items)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
bool isRemovedItem = false;
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(m_Cart, () => $"m_Cart is null !!!");
|
||||
var cart_attribute = m_Cart.getEntityAttribute<CartAttribute>();
|
||||
if (cart_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get cart attribute : {nameof(CartAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, isRemovedItem);
|
||||
}
|
||||
|
||||
foreach (var del_cart_item in del_cart_items)
|
||||
{
|
||||
if (EnumHelper.tryParse<CurrencyType>(del_cart_item.BuyType, out var currencyType) == false)
|
||||
{
|
||||
err_msg = $"Enum Pase Failed. BuyType : {del_cart_item.BuyType}";
|
||||
result.setFail(ServerErrorCode.CartInvalidCurrencyType, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, isRemovedItem);
|
||||
}
|
||||
|
||||
if(MetaData.Instance._ItemTable.TryGetValue(del_cart_item.ItemId, out var itemData) == false)
|
||||
{
|
||||
err_msg = $"Not found meta of Item !!! : ItemMetaId:{del_cart_item.ItemId} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CartMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, isRemovedItem);
|
||||
}
|
||||
|
||||
int cur_count = 0;
|
||||
foreach(var category_cart_items in cart_attribute.CartItems.Values)
|
||||
{
|
||||
if (category_cart_items.TryGetValue((META_ID)del_cart_item.ItemId, out cur_count) == false)
|
||||
continue;
|
||||
|
||||
if (del_cart_item.Count > cur_count)
|
||||
{
|
||||
err_msg = $"Argument count is bigger then cart Item count. cur_count : {cur_count}, req_buy_count : {del_cart_item.Count}";
|
||||
result.setFail(ServerErrorCode.CartStackCountNotEnough, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, isRemovedItem);
|
||||
}
|
||||
|
||||
category_cart_items[(META_ID)del_cart_item.ItemId] = cur_count - del_cart_item.Count;
|
||||
if (cur_count - del_cart_item.Count == 0)
|
||||
{
|
||||
category_cart_items.Remove((META_ID)del_cart_item.ItemId);
|
||||
isRemovedItem = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(cur_count == 0)
|
||||
{
|
||||
err_msg = $"Not found itemid from category_cart_items. itemId : {del_cart_item.ItemId}";
|
||||
result.setFail(ServerErrorCode.CartItemNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, isRemovedItem);
|
||||
}
|
||||
}
|
||||
|
||||
cart_attribute.modifiedEntityAttribute();
|
||||
|
||||
return (result, isRemovedItem);
|
||||
}
|
||||
|
||||
private async Task<Result> PayCurrencyForItem(List<CartItemInfo> buy_cart_items)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var my_shop_product = getOwner();
|
||||
var player = my_shop_product.getRootParent() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var money_action = player.getEntityAction<MoneyAction>();
|
||||
if (null == money_action)
|
||||
{
|
||||
var err_msg = $"Fail to get Money Action : {nameof(MoneyAction)}.";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
Dictionary<CurrencyType, double> changeMoneys = new Dictionary<CurrencyType, double>();
|
||||
|
||||
foreach(var buy_item in buy_cart_items)
|
||||
{
|
||||
if(MetaData.Instance._ItemTable.TryGetValue(buy_item.ItemId, out var item_data) == false)
|
||||
{
|
||||
var err_msg = $"Not Found ItemDataTable Item Id : {buy_item.ItemId}";
|
||||
result.setFail(ServerErrorCode.CartMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = player.checkItemFirstPurchaseItemCount(buy_item.ItemId, buy_item.Count);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var check_currency_type = ShopHelper.checkCurrencyTypeFromCurrencyId(item_data.Buy_id);
|
||||
if (check_currency_type.result.isFail()) return check_currency_type.result;
|
||||
|
||||
if (changeMoneys.TryGetValue(check_currency_type.currencyType, out var price) == false)
|
||||
{
|
||||
changeMoneys.Add(check_currency_type.currencyType, 0);
|
||||
}
|
||||
|
||||
var item_first_purchase_history_agent_action = player.getEntityAction<ItemFirstPurchaseHistoryAgentAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(item_first_purchase_history_agent_action, () => $"item_first_purchase_history_agent_action is null !!!");
|
||||
|
||||
var item_price = item_data.BuyPrice;
|
||||
if (item_first_purchase_history_agent_action.isItemFirstPurchase(buy_item.ItemId))
|
||||
{
|
||||
item_price = ((item_data.BuyPrice * 100) - (item_data.BuyPrice * item_data.Buy_Discount_Rate)) / 100;
|
||||
}
|
||||
|
||||
changeMoneys[check_currency_type.currencyType] += (-1 * item_price * buy_item.Count);
|
||||
}
|
||||
|
||||
foreach(var changeMoney in changeMoneys)
|
||||
{
|
||||
result = await money_action.changeMoney(changeMoney.Key, changeMoney.Value);
|
||||
if (result.isFail()) return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<(Result result, List<Item>? changed_Items)> TakeCartItem(List<CartItemInfo> buy_cart_items)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
||||
if (null == inventory_action)
|
||||
{
|
||||
var err_msg = $"Fail to get Inventory Action : {nameof(InventoryActionBase)}.";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
List<Item> buy_changed_items = new List<Item>();
|
||||
foreach(var buy_item in buy_cart_items)
|
||||
{
|
||||
(result, var changed_items) = await inventory_action.tryTakalbleToBag((META_ID)buy_item.ItemId, (ushort)buy_item.Count);
|
||||
if (result.isFail()) return (result, null);
|
||||
|
||||
buy_changed_items.AddRange(changed_items);
|
||||
}
|
||||
|
||||
return (result, buy_changed_items);
|
||||
}
|
||||
|
||||
public Cart getCart()
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(m_Cart, () => $"m_Cart is null !!!");
|
||||
return m_Cart;
|
||||
}
|
||||
|
||||
async Task<Result> updateItemFirstPurchaseHistory(List<CartItemInfo> buy_cart_items)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var item_first_purchase_history_agent_action = player.getEntityAction<ItemFirstPurchaseHistoryAgentAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(item_first_purchase_history_agent_action, () => $"item_first_purchase_history_agent_action is null !!!");
|
||||
|
||||
foreach (var buy_item in buy_cart_items)
|
||||
{
|
||||
if (!item_first_purchase_history_agent_action.isItemFirstPurchase(buy_item.ItemId))
|
||||
continue;
|
||||
|
||||
result = await item_first_purchase_history_agent_action.tryAddItemFirstPurchaseHistoryFromMetaId(buy_item.ItemId);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
58
GameServer/Contents/Cart/Cart.cs
Normal file
58
GameServer/Contents/Cart/Cart.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class Cart : EntityBase
|
||||
{
|
||||
public Cart(Player parent)
|
||||
: base(EntityType.Cart, parent)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
var direct_parent = getDirectParent();
|
||||
NullReferenceCheckHelper.throwIfNull(direct_parent, () => $"direct_parent is null !!!");
|
||||
addEntityAttribute(new CartAttribute(this, direct_parent));
|
||||
|
||||
return await base.onInit();
|
||||
}
|
||||
|
||||
public override string toBasicString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public override string toSummaryString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public List<CartItemInfo> toCartItemData4Client()
|
||||
{
|
||||
var cart_item_list_4_client = new List<CartItemInfo>();
|
||||
var cart_attribute = getEntityAttribute<CartAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(cart_attribute, () => $"cart_attribute is null !!!");
|
||||
|
||||
foreach (var cart_category_item in cart_attribute.CartItems)
|
||||
{
|
||||
foreach(var cartitem in cart_category_item.Value)
|
||||
{
|
||||
CartItemInfo cart_item = new CartItemInfo();
|
||||
cart_item.BuyType = cart_category_item.Key.ToString();
|
||||
cart_item.ItemId = (Int32)cartitem.Key;
|
||||
cart_item.Count = cartitem.Value;
|
||||
cart_item_list_4_client.Add(cart_item);
|
||||
}
|
||||
}
|
||||
|
||||
return cart_item_list_4_client;
|
||||
}
|
||||
}
|
||||
}
|
||||
117
GameServer/Contents/Cart/DBQuery/DBQCartReadAll.cs
Normal file
117
GameServer/Contents/Cart/DBQuery/DBQCartReadAll.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using Amazon.DynamoDBv2.DocumentModel;
|
||||
using GameServer;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class DBQCartReadAll : QueryExecutorBase
|
||||
{
|
||||
private string m_combination_key_for_pk = string.Empty;
|
||||
|
||||
private string m_pk = string.Empty;
|
||||
|
||||
private CartDoc m_to_read_cart_docs = new();
|
||||
|
||||
public DBQCartReadAll(string combinationKeyForPK)
|
||||
: base(typeof(DBQCartReadAll).Name)
|
||||
{
|
||||
m_combination_key_for_pk = combinationKeyForPK;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//=====================================================================================
|
||||
public override Task<Result> onPrepareQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var doc = new CartDoc();
|
||||
doc.setCombinationKeyForPK(m_combination_key_for_pk);
|
||||
|
||||
var error_code = doc.onApplyPKSK();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(error_code, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
m_pk = doc.getPK();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var query_batch = getQueryBatch();
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => "query_batch is null !!!");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
var query_config = db_connector.makeQueryConfigForReadByPKOnly(m_pk);
|
||||
|
||||
(result, var read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<CartDoc>(query_config, eventTid: query_batch.getTransId());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (read_docs.Count == 1)
|
||||
{
|
||||
var cart_action = owner.getEntityAction<CartAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(cart_action, () => "cart_action is null !!!");
|
||||
|
||||
result = cart_action.AddCartFromDoc(read_docs[0]);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
m_to_read_cart_docs = read_docs[0];
|
||||
}
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
public CartDoc getToReadItemDocs() => m_to_read_cart_docs;
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseCommit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
public new Player? getOwner() => getQueryBatch()?.getLogActor() as Player;
|
||||
}
|
||||
}
|
||||
32
GameServer/Contents/Cart/Log/CartBusinessLog.cs
Normal file
32
GameServer/Contents/Cart/Log/CartBusinessLog.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CartBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private CartLogData m_data_to_log;
|
||||
public CartBusinessLog(CartLogData log_data_param)
|
||||
: base(LogDomainType.Cart)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new CartLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
21
GameServer/Contents/Cart/Log/CartBusinessLogHelper.cs
Normal file
21
GameServer/Contents/Cart/Log/CartBusinessLogHelper.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using ServerCommon;
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
static public class CartBusinessLogHelper
|
||||
{
|
||||
static public CartLogData toLogInfo(List<(META_ID, int)> deltaCartData)
|
||||
{
|
||||
var logData = new CartLogData();
|
||||
logData.setInfo(deltaCartData);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this CartLogData logData, List<(META_ID, int)> deltaCartData)
|
||||
{
|
||||
logData.deltaItemDataList = deltaCartData;
|
||||
}
|
||||
}
|
||||
}
|
||||
108
GameServer/Contents/Cart/PacketHandler/AddCartPacketHandler.cs
Normal file
108
GameServer/Contents/Cart/PacketHandler/AddCartPacketHandler.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.AddCartReq), typeof(AddCartPacketHandler), typeof(GameLoginListener))]
|
||||
public class AddCartPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_ADD_CART(Player player, Result result, META_ID item_meta_id = 0, Int32 count = 0)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.AddCartRes = new AddCartRes();
|
||||
|
||||
if(count != 0 && item_meta_id != 0)
|
||||
{
|
||||
ack_packet.Response.AddCartRes.ChangeItem = new();
|
||||
ack_packet.Response.AddCartRes.ChangeItem.ItemId = (Int32)item_meta_id;
|
||||
ack_packet.Response.AddCartRes.ChangeItem.Count = count;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
|
||||
|
||||
var cart_action = entity_player.getEntityAction<CartAction>();
|
||||
if (cart_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get cart action : {nameof(CartAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_ADD_CART(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.AddCartReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_ADD_CART(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.AddCartReq;
|
||||
|
||||
if(EnumHelper.tryParse<CurrencyType>(request.ItemInfo.BuyType, out var currency_type) == false)
|
||||
{
|
||||
err_msg = $"is Not Defined currencyType !!! currencyType : {request.ItemInfo.BuyType} - {entity_player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CartInvalidCurrencyType, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
send_S2C_ACK_ADD_CART(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await cart_action.AddCartProcess((META_ID)request.ItemInfo.ItemId, request.ItemInfo.Count, currency_type);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to AddCartProcess() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_ADD_CART(player, errorResult);
|
||||
}
|
||||
}
|
||||
120
GameServer/Contents/Cart/PacketHandler/BuyCartPacketHandler.cs
Normal file
120
GameServer/Contents/Cart/PacketHandler/BuyCartPacketHandler.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.BuyCartReq), typeof(BuyCartPacketHandler), typeof(GameLoginListener))]
|
||||
public class BuyCartPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_BUY_CART(Player player, Result result, List<Item>? items = null)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.BuyCartRes = new BuyCartRes();
|
||||
|
||||
if (result.isSuccess() && items != null)
|
||||
{
|
||||
var account_attribute = player.getEntityAttribute<AccountAttribute>();
|
||||
var level_attribute = player.getEntityAttribute<LevelAttribute>();
|
||||
var money_attribute = player.getEntityAttribute<MoneyAttribute>();
|
||||
var nickname_attribute = player.getEntityAttribute<NicknameAttribute>();
|
||||
|
||||
var char_info = new CharInfo
|
||||
{
|
||||
Level = (int)level_attribute!.Level,
|
||||
Exp = (int)level_attribute.Exp,
|
||||
|
||||
Gold = money_attribute!.Gold,
|
||||
Sapphire = money_attribute.Sapphire,
|
||||
Calium = money_attribute.Calium,
|
||||
Ruby = money_attribute.Ruby,
|
||||
|
||||
Usergroup = account_attribute!.AuthAdminLevelType.ToString(),
|
||||
Operator = (int)account_attribute.AuthAdminLevelType,
|
||||
|
||||
DisplayName = nickname_attribute!.Nickname,
|
||||
LanguageInfo = (int)account_attribute.LanguageType,
|
||||
|
||||
IsIntroComplete = 1
|
||||
};
|
||||
ack_packet.Response.BuyCartRes.CurrencyInfo = char_info;
|
||||
ack_packet.Response.BuyCartRes.Items.AddRange(items.Select(info => info.toItemData4Client()));
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
|
||||
|
||||
var cart_action = entity_player.getEntityAction<CartAction>();
|
||||
if (cart_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get cart action : {nameof(CartAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_BUY_CART(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.BuyCartReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_BUY_CART(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.BuyCartReq;
|
||||
result = await cart_action.BuyCartProcess(request.ItemInfos.ToList());
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to BuyCartProcess() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var cart_item_info in request.ItemInfos.ToList())
|
||||
{
|
||||
await QuestManager.It.QuestCheck(entity_player, new QuestItem(EQuestEventTargetType.ITEM, EQuestEventNameType.BOUGHT, cart_item_info.ItemId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_BUY_CART(player, errorResult);
|
||||
}
|
||||
}
|
||||
36
GameServer/Contents/Cart/PacketHandler/CartNotifyHelper.cs
Normal file
36
GameServer/Contents/Cart/PacketHandler/CartNotifyHelper.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public static class CartNotifyHelper
|
||||
{
|
||||
public static bool send_S2C_NTF_CART(this Player player)
|
||||
{
|
||||
var cart_action = player.getEntityAction<CartAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(cart_action, () => $"cart_action is null !!!");
|
||||
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.CartNoti = new();
|
||||
|
||||
var cart = cart_action.getCart();
|
||||
|
||||
if (cart != null)
|
||||
{
|
||||
noti_packet.Message.CartNoti.ItemList.AddRange(cart.toCartItemData4Client());
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, noti_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.DelCartReq), typeof(DelCartPacketHandler), typeof(GameLoginListener))]
|
||||
public class DelCartPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_DEL_CART(Player player, Result result, bool isRemoveItem = false)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.DelCartRes = new DelCartRes();
|
||||
|
||||
ack_packet.Response.DelCartRes.IsRemoveItem = isRemoveItem ? 1 : 0;
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
|
||||
|
||||
var cart_action = entity_player.getEntityAction<CartAction>();
|
||||
if (cart_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get cart action : {nameof(CartAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_DEL_CART(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.DelCartReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_DEL_CART(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.DelCartReq;
|
||||
|
||||
result = await cart_action.DeleteCartProcess(request.ItemInfos.ToList());
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to DelCartProcess() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_DEL_CART(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.GetCartReq), typeof(GetCartPacketHandler), typeof(GameLoginListener))]
|
||||
public class GetCartPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_GET_CART(Player player, Result result, Cart? cart = null)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.GetCartRes = new GetCartRes();
|
||||
|
||||
if(cart != null)
|
||||
{
|
||||
ack_packet.Response.GetCartRes.ItemList.AddRange(cart.toCartItemData4Client());
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => "player is null !!!");
|
||||
|
||||
var cart_action = entity_player.getEntityAction<CartAction>();
|
||||
if (cart_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get cart action : {nameof(CartAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_GET_CART(entity_player, result);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
result = cart_action.GetCart4Client();
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to GetCart4Client() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
send_S2C_ACK_GET_CART(entity_player, result);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_GET_CART(player, errorResult);
|
||||
}
|
||||
}
|
||||
180
GameServer/Contents/Channel/Action/ChannelAction.cs
Normal file
180
GameServer/Contents/Channel/Action/ChannelAction.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using GameServer.PacketHandler;
|
||||
|
||||
|
||||
using USER_GUID = System.String;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class ChannelAction : EntityActionBase
|
||||
{
|
||||
public ChannelAction(EntityBase owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public Result tryGetChannelList()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var channel_list = server_logic.getChannelManager().getWholeChannels();
|
||||
|
||||
GetChannelListPacketHandler.send_S2C_ACK_GET_CHANNEL_LIST(player, result, channel_list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<(Result result, int possible_remaining_time)> tryMoveChannel(int move_channel) // TODO: chan redis간 transaction 처리가 되어있지 않다.
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var config = server_logic.getServerConfig();
|
||||
|
||||
if (move_channel == config.getChannelNo())
|
||||
{
|
||||
err_msg = $"Select Same Channel. !!! - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ChannelMoveSameChannel, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
(result, var serverInfo) = await server_logic.getServerInfoByChannel(config.getWorldId(), move_channel);
|
||||
if (serverInfo == null)
|
||||
{
|
||||
err_msg = $"Failed ValidServerNotFound WorldServerName : {server_logic.getServerName()} move_channel : {move_channel} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ValidServerNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
if (serverInfo.Sessions + serverInfo.Reservation + serverInfo.ReturnCount >= serverInfo.Capacity)
|
||||
{
|
||||
err_msg = $"Server is Full : {server_logic.getServerName()}, Channel : {move_channel}";
|
||||
result.setFail(ServerErrorCode.TargetServerUserCountExceed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
// 0. 채널 이동시 조건 체크
|
||||
var location_attribute = getOwner().getEntityAttribute<LocationAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(location_attribute, () => $"location_attribute is null !!!");
|
||||
|
||||
var last_move_time = location_attribute.MoveChannelTime.ToDateTime();
|
||||
var possible_remaining_time = last_move_time.AddSeconds(ServerCommon.MetaHelper.GameConfigMeta.ChannelChangeCoolTime) - DateTimeHelper.Current;
|
||||
if (possible_remaining_time.TotalSeconds > 0)
|
||||
{
|
||||
err_msg = $"fail to move channel !!! : invalid channel cool time - {ServerCommon.MetaHelper.GameConfigMeta.ChannelChangeCoolTime} / possible_remaining_time - {possible_remaining_time.TotalSeconds}";
|
||||
result.setFail(ServerErrorCode.ChannelInvalidMoveCoolTime, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, (int)possible_remaining_time.TotalSeconds);
|
||||
}
|
||||
|
||||
// 1. 예약 요청
|
||||
var message = new ServerMessage.Types.GS2GS_REQ_RESERVATION_ENTER_TO_SERVER();
|
||||
message.MoveType = ServerMoveType.Force;
|
||||
message.RequestServerName = server_logic.getServerName();
|
||||
message.RequestUserGuid = player.getUserGuid();
|
||||
|
||||
var reserved = await server_logic.getReservationManager().registerReservationEnterToServer(message, serverInfo.Name);
|
||||
|
||||
// 2. 예약 실패 체크
|
||||
if (null == reserved)
|
||||
{
|
||||
err_msg = $"Failed to reservation enter to game server!!! - {nameof(tryMoveChannel)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
result.setFail(ServerErrorCode.FailedToReservationEnter, err_msg);
|
||||
return (result, 0);
|
||||
}
|
||||
|
||||
// 3. 이동 처리
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "MoveChannel", moveChannelDelegate);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransaction() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return (result, 0);
|
||||
|
||||
async Task<Result> moveChannelDelegate() => await moveChannelAsync(player, serverInfo);
|
||||
}
|
||||
|
||||
private async Task<Result> moveChannelAsync(Player player, ServerInfo serverInfo)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var location_attribute = player.getEntityAttribute<LocationAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(location_attribute, () => $"location_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
location_attribute.MoveChannelTime = DateTimeHelper.Current.ToTimestamp();
|
||||
|
||||
result = await GameZoneMoveHelper.moveToAnotherChannel(player, serverInfo, null);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to moveToAnotherChannel() !!! : {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var account_attribute = player.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var gameServer_connection_info = new ServerConnectInfo
|
||||
{
|
||||
ServerAddr = serverInfo.Address,
|
||||
ServerPort = serverInfo.Port,
|
||||
Otp = account_attribute.OtpForServerConnect,
|
||||
};
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.None, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
batch.addQuery(new QueryFinal());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
MoveChannelPacketHandler.send_S2C_ACK_MOVE_CHANNEL(player, result, gameServer_connection_info, 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.GetChannelListReq), typeof(GetChannelListPacketHandler), typeof(GameLoginListener))]
|
||||
public class GetChannelListPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_GET_CHANNEL_LIST(Player player, Result result, List<GameChannel>? channel_list)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.GetChannelListRes = new GetChannelListRes();
|
||||
|
||||
if(channel_list != null)
|
||||
{
|
||||
var client_ui_channel_list = channel_list.Select(x => new ChannelInfo() { Channel = x.channel, Trafficlevel = x.trafficlevel }).ToList();
|
||||
ack_packet.Response.GetChannelListRes.ChannelInfoList.AddRange(client_ui_channel_list);
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => "player is null !!!");
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var channel_action = entity_player.getEntityAction<ChannelAction>();
|
||||
if (channel_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get chat action : {nameof(ChannelAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_GET_CHANNEL_LIST(entity_player, result, null);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
result = channel_action.tryGetChannelList();
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_GET_CHANNEL_LIST(entity_player, result, null);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_GET_CHANNEL_LIST(player, errorResult, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.MoveChannelReq), typeof(MoveChannelPacketHandler), typeof(GameLoginListener))]
|
||||
public class MoveChannelPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_MOVE_CHANNEL(Player player, Result result, ServerConnectInfo? serverConnectInfo, int possibleRemainingTime)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.MoveChannelRes = new MoveChannelRes();
|
||||
ack_packet.Response.MoveChannelRes.PossibleRemainingTime = possibleRemainingTime;
|
||||
|
||||
if(serverConnectInfo != null)
|
||||
{
|
||||
ack_packet.Response.MoveChannelRes.GameServerConnectInfo = serverConnectInfo;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
|
||||
var request = recv_msg.Request.MoveChannelReq;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var selected_character = player_action.getSelectedCharacter();
|
||||
if (null == selected_character)
|
||||
{
|
||||
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_MOVE_CHANNEL(player, result, null, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
var character_action = selected_character.getEntityAction<CharacterAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(character_action, () => $"character_action is null !!! - {selected_character.toBasicString()}");
|
||||
if (character_action.isFarming())
|
||||
{
|
||||
err_msg = $"Character is Farming !!! - {selected_character.toBasicString()}, {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.FarimgState, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_MOVE_CHANNEL(player, result, null, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
var channel_action = player.getEntityAction<ChannelAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(channel_action, () => $"channel_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, var possible_remaining_time) = await channel_action.tryMoveChannel(request.Channel);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to tryMoveChannel() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_MOVE_CHANNEL(player, result, null, possible_remaining_time);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_MOVE_CHANNEL(player, errorResult, null, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
using Amazon.Runtime.Internal.Endpoints.StandardLibrary;
|
||||
using GameServer.PacketHandler;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class CharacterProfileAction : EntityActionBase
|
||||
{
|
||||
public CharacterProfileAction(EntityBase owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public async Task<Result> saveCharacterProfile(string sns_link, string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var fn_save_character_profile = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
|
||||
var character_profile_attribute = player.getEntityAttribute<CharacterProfileAttribute>();
|
||||
if (character_profile_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get character profile attribute : {nameof(CharacterProfileAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
SaveCharacterProfilePacketHandler.send_S2C_ACK_SAVE_CHARACTER_PROFILE(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
character_profile_attribute.SNSLick = sns_link;
|
||||
character_profile_attribute.Message = message;
|
||||
|
||||
character_profile_attribute.modifiedEntityAttribute();
|
||||
|
||||
var task_log_data = CharacterProfileBusinessLogHelper.toLogInfo(character_profile_attribute);
|
||||
invokers.Add(new CharacterProfileBusinessLog(task_log_data));
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.UpdateCharacterProfile
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
SaveCharacterProfilePacketHandler.send_S2C_ACK_SAVE_CHARACTER_PROFILE(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
SaveCharacterProfilePacketHandler.send_S2C_ACK_SAVE_CHARACTER_PROFILE(player, result);
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "SaveCharacterProfile", fn_save_character_profile);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> getTargetCharacterProfile(string target_nickname)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var player_manager = server_logic.getPlayerManager();
|
||||
player_manager.tryGetUserBySubKey(target_nickname, out var target_player);
|
||||
|
||||
GetCharProfileRes? res = null;
|
||||
if (target_player == null)
|
||||
{
|
||||
(result, res) = await getOtherServerCharacterProfile(target_nickname);
|
||||
if (result.isFail())
|
||||
{
|
||||
GetCharacterProfilePacketHandler.send_S2C_ACK_GET_CHARACTER_PROFILE(player, result, null);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(result, res) = getSameServerCharacterProfile(target_player);
|
||||
if (result.isFail())
|
||||
{
|
||||
GetCharacterProfilePacketHandler.send_S2C_ACK_GET_CHARACTER_PROFILE(player, result, null);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
GetCharacterProfilePacketHandler.send_S2C_ACK_GET_CHARACTER_PROFILE(player, result, res);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<(Result, GetCharProfileRes?)> getOtherServerCharacterProfile(string target_nickname)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
|
||||
(result, var nickname_attrib) = await NicknameHelper.findNickname(target_nickname);
|
||||
if (result.isFail()) return (result, null);
|
||||
NullReferenceCheckHelper.throwIfNull(nickname_attrib, () => $"nickname_attrib is null !!!");
|
||||
|
||||
(result, var found_account_attrib) = await dynamo_db_client.simpleQueryDocTypeToAttrib<AccountBaseDoc, AccountBaseAttrib>(nickname_attrib.AccountId);
|
||||
if (result.isFail()) return (result, null);
|
||||
NullReferenceCheckHelper.throwIfNull(found_account_attrib, () => $"found_account_attrib is null !!!");
|
||||
|
||||
(result, var found_character_profile_attrib) = await dynamo_db_client.simpleQueryDocTypeToAttrib<CharacterProfileDoc, CharacterProfileAttrib>(nickname_attrib.UserGuid);
|
||||
if (result.isFail()) return (result, null);
|
||||
NullReferenceCheckHelper.throwIfNull(found_character_profile_attrib, () => $"found_character_profile_attrib is null !!!");
|
||||
|
||||
var res = new GetCharProfileRes();
|
||||
res.PublicGuid = ServerCore.EncryptionHelper.encryptTextByDES(found_account_attrib.UserGuid, EncryptData.DESEncryptKey, EncryptData.DESEncryptIv);
|
||||
res.NickName = target_nickname;
|
||||
res.SNSLink = found_character_profile_attrib.SNSLick;
|
||||
res.Message = found_character_profile_attrib.Message;
|
||||
res.Language = (int)found_account_attrib.LanguageType;
|
||||
|
||||
return (result, res);
|
||||
}
|
||||
|
||||
private (Result, GetCharProfileRes?) getSameServerCharacterProfile(Player target_player)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var character_profile_attribute = target_player.getEntityAttribute<CharacterProfileAttribute>();
|
||||
if (character_profile_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get character profile attribute : {nameof(CharacterProfileAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var account_attribute = target_player.getEntityAttribute<AccountAttribute>();
|
||||
if (account_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get account attribute : {nameof(AccountAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var ability_action = target_player.getEntityAction<AbilityAction>();
|
||||
if (ability_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get ability action : {nameof(AbilityAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var target_abilities = ability_action.getAbilities();
|
||||
|
||||
var res = new GetCharProfileRes();
|
||||
res.PublicGuid = EncryptionHelper.encryptTextByDES(account_attribute.UserGuid, EncryptData.DESEncryptKey, EncryptData.DESEncryptIv);
|
||||
res.NickName = target_player.getUserNickname();
|
||||
res.SNSLink = character_profile_attribute.SNSLick;
|
||||
res.Message = character_profile_attribute.Message;
|
||||
res.Language = (int)account_attribute.LanguageType;
|
||||
|
||||
foreach(var ability in target_abilities)
|
||||
{
|
||||
res.Attributeinfo.Add(new AttributeInfo() { Attributeid = (int)ability.Key, Value = ability.Value });
|
||||
}
|
||||
|
||||
return (result, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CharacterProfileBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private CharacterProfileLogData m_data_to_log;
|
||||
public CharacterProfileBusinessLog(CharacterProfileLogData log_data_param)
|
||||
: base(LogDomainType.Craft)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new CharacterProfileLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using ServerCommon;
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
static public class CharacterProfileBusinessLogHelper
|
||||
{
|
||||
static public CharacterProfileLogData toLogInfo(CharacterProfileAttribute attribute)
|
||||
{
|
||||
var logData = new CharacterProfileLogData();
|
||||
logData.setInfo(attribute);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this CharacterProfileLogData logData, CharacterProfileAttribute attribute)
|
||||
{
|
||||
logData.SNSLick = attribute.SNSLick;
|
||||
logData.Message = attribute.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.GetCharProfileReq), typeof(GetCharacterProfilePacketHandler), typeof(GameLoginListener))]
|
||||
public class GetCharacterProfilePacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_GET_CHARACTER_PROFILE(Player player, Result result, GetCharProfileRes? res = null)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
if(res != null)
|
||||
{
|
||||
ack_packet.Response.GetCharProfileRes = res;
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => "player is null !!!");
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var character_profile_action = entity_player.getEntityAction<CharacterProfileAction>();
|
||||
if (character_profile_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get character profile action : {nameof(CharacterProfileAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_GET_CHARACTER_PROFILE(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.GetCharProfileReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_GET_CHARACTER_PROFILE(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.GetCharProfileReq;
|
||||
|
||||
result = await character_profile_action.getTargetCharacterProfile(request.NickName);
|
||||
if(result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to getTargetCharacterProfile() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_GET_CHARACTER_PROFILE(player, errorResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.SaveCharProfileReq), typeof(SaveCharacterProfilePacketHandler), typeof(GameLoginListener))]
|
||||
public class SaveCharacterProfilePacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_SAVE_CHARACTER_PROFILE(Player player, Result result)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.SaveCharProfileRes = new();
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
ArgumentNullException.ThrowIfNull(entity_player);
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var character_profile_action = entity_player.getEntityAction<CharacterProfileAction>();
|
||||
if (character_profile_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get character profile action : {nameof(CharacterProfileAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
send_S2C_ACK_SAVE_CHARACTER_PROFILE(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.SaveCharProfileReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_SAVE_CHARACTER_PROFILE(entity_player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.SaveCharProfileReq;
|
||||
|
||||
result = await character_profile_action.saveCharacterProfile(request.SNSLink, request.Message);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to saveCharacterProfile() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
await QuestManager.It.QuestCheck(entity_player, new QuestAvatarProfile(EQuestEventTargetType.AVATARPROFILE, EQuestEventNameType.EDITED));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_SAVE_CHARACTER_PROFILE(player, errorResult);
|
||||
}
|
||||
}
|
||||
271
GameServer/Contents/Chat/Action/ChatAction.cs
Normal file
271
GameServer/Contents/Chat/Action/ChatAction.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class ChatAction : EntityActionBase
|
||||
{
|
||||
public ChatAction(EntityBase owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 일반 주변 채팅
|
||||
public Result NormalChat(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT_BROADCAST(player, ChatType.Normal, player.getUserNickname(), string.Empty, PlayerStateType.None, message);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatNormal);
|
||||
|
||||
var cellPos = game_zone_action.GetPlayerCellPos(player);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, cellPos);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 채널 서버 내 채팅
|
||||
public Result ChannelChat(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"server_logic is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var receivers = server_logic.getPlayerManager().getUsers();
|
||||
foreach(var receiver in receivers)
|
||||
{
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(receiver.Value, ChatType.Channel, player.getUserNickname(), string.Empty, PlayerStateType.None, message);
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatChannel);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, string.Empty);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 전서버 채팅
|
||||
public Result NoticeChat(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"server_logic is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
// GM인지 확인
|
||||
//if (AccountAuthorityManager.Instance.IsWhiteListUser(player.getAccountId()) == false)
|
||||
//{
|
||||
// err_msg = $"Not Enough Authority to NoticeChat : player - {player.toBasicString()}";
|
||||
// result.setFail(ServerErrorCode.NotEnoughAuthority, err_msg);
|
||||
// Log.getLogger().error(err_msg);
|
||||
// ChatPacketHandler.send_S2C_ACK_CHAT(player, result, ChatType.Notice, player.getUserNickname(), string.Empty, string.Empty, PlayerStateType.None, message);
|
||||
// return result;
|
||||
//}
|
||||
|
||||
var rabbitMQ4Game = server_logic.getRabbitMqConnector() as RabbitMQ4Game;
|
||||
NullReferenceCheckHelper.throwIfNull(rabbitMQ4Game, () => $"rabbitMQ4Game is null !!!");
|
||||
|
||||
|
||||
rabbitMQ4Game.sendChat(message, player.getUserNickname(), ChatType.Notice);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatNotice);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, string.Empty);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 귓속말 채팅
|
||||
public async Task<Result> WhisperChat(string receiver_nickname, string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var rabbitMQ4Game = server_logic.getRabbitMqConnector() as RabbitMQ4Game;
|
||||
NullReferenceCheckHelper.throwIfNull(rabbitMQ4Game, () => $"rabbitMQ4Game is null !!!");
|
||||
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
|
||||
if (receiver_nickname == player.getUserNickname())
|
||||
{
|
||||
err_msg = $"Can't Send Chat to Self. nickname : {receiver_nickname}";
|
||||
result.setFail(ServerErrorCode.ChatSendSelfFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, var nickname_attrib) = await NicknameHelper.findNickname(receiver_nickname);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Not Found Target. nickname : {receiver_nickname}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(nickname_attrib, () => $"nickname_attrib is null !!!");
|
||||
var receiver_user_guid = nickname_attrib.UserGuid;
|
||||
|
||||
var login_cache_request = new LoginCacheOtherUserRequest(player, server_logic.getRedisConnector(), nickname_attrib.UserGuid);
|
||||
result = await login_cache_request.fetchLogin();
|
||||
var login_cache = login_cache_request.getLoginCache();
|
||||
if (result.isFail() || login_cache == null)
|
||||
{
|
||||
err_msg = $"Logoff user : target_usenicknamer - {receiver_nickname}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotLogIn, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
var user_block_action = player.getEntityAction<BlockUserAgentAction>();
|
||||
if (user_block_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get user block action : {nameof(BlockUserAgentAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
//내가 차단한경우
|
||||
if (user_block_action.isBlockUser(receiver_user_guid))
|
||||
{
|
||||
err_msg = $"Failed chat with blocked user.";
|
||||
result.setFail(ServerErrorCode.ChatBlockUserCannotWhisper, err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
//상대방이 차단한경우 상대방에겐 보내지 않고 정상 처리 되도록
|
||||
(result, bool isblocked) = await user_block_action.amIBockedFromOthers(receiver_user_guid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isblocked == true)
|
||||
{
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), receiver_user_guid, login_cache.State, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (login_cache.CurrentServer != server_logic.getServerName())
|
||||
{
|
||||
ServerMessage chatMessage = new();
|
||||
chatMessage.Chat = new();
|
||||
chatMessage.Chat.Type = ChatType.Whisper;
|
||||
chatMessage.Chat.SenderNickName = player.getUserNickname();
|
||||
chatMessage.Chat.ReceiverGuid = receiver_user_guid;
|
||||
chatMessage.Chat.Receiverstate = login_cache.State;
|
||||
chatMessage.Chat.Message = message;
|
||||
|
||||
rabbitMQ4Game.SendMessage(login_cache.CurrentServer, chatMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(server_logic.getPlayerManager().tryGetUserByPrimaryKey(receiver_user_guid, out var receiver) == false)
|
||||
{
|
||||
err_msg = $"Failed to get player from player manager : receiver_user_guid - {receiver_user_guid}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotLogIn, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(receiver == null)
|
||||
{
|
||||
err_msg = $"Failed to get player from player manager : receiver_user_guid - {receiver_user_guid}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotLogIn, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(receiver, ChatType.Whisper, player.getUserNickname(), receiver_nickname, login_cache.State, message);
|
||||
}
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(player, ChatType.Whisper, player.getUserNickname(), receiver_nickname, login_cache.State, message);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatWhisper);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, receiver_nickname);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 파티 채팅
|
||||
public async Task<Result> PartyChat(string message)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var personal_party_action = player.getEntityAction<PersonalPartyAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(personal_party_action, () => $"personal_party_action is null !!!");
|
||||
|
||||
var result = await personal_party_action.sendPartyChat(message);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatParty);
|
||||
|
||||
//personal_party_action.getPersonalParty().
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, string.Empty);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
278
GameServer/Contents/Chat/ChatCommand.cs
Normal file
278
GameServer/Contents/Chat/ChatCommand.cs
Normal file
@@ -0,0 +1,278 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Claims;
|
||||
|
||||
|
||||
using Amazon.DynamoDBv2.Model;
|
||||
using Amazon.DynamoDBv2;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using GameServer.PacketHandler;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
using static ClientToGameMessage.Types;
|
||||
|
||||
|
||||
using SESSION_ID = System.Int32;
|
||||
using WORLD_META_ID = System.UInt32;
|
||||
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 GameServer;
|
||||
|
||||
public class ChatCommand : Attribute
|
||||
{
|
||||
Dictionary<string, ChatCommandBase> command_base_map = new Dictionary<string, ChatCommandBase>();
|
||||
|
||||
public ChatCommand()
|
||||
{
|
||||
loadChatCommand();
|
||||
|
||||
}
|
||||
|
||||
private void loadChatCommand()
|
||||
{
|
||||
// ChatCommand 클래스의 모든 메서드를 가져옵니다.
|
||||
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
ChatCommandAttribute[] attributes = (ChatCommandAttribute[])type.GetCustomAttributes(typeof(ChatCommandAttribute), false);
|
||||
|
||||
|
||||
foreach (var attrib in attributes)
|
||||
{
|
||||
var command_key = attrib.getCommand();
|
||||
if (command_key == null)
|
||||
{
|
||||
Log.getLogger().error($"ChatCommand Key is null !!!, in ChatCommandAttributes : {attrib.getHandlerClass().FullName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var handler_class = Activator.CreateInstance(attrib.getHandlerClass()) as ChatCommandBase;
|
||||
if (handler_class == null)
|
||||
{
|
||||
Log.getLogger().error($"Failed to create ChatCommand !!! : commandKey:{command_key}");
|
||||
continue;
|
||||
}
|
||||
|
||||
handler_class.setAuthAdminLevelType(attrib.getAdminLevel());
|
||||
handler_class.setClassName(attrib.getHandlerClass().Name);
|
||||
if (command_base_map.TryAdd(command_key, handler_class) == false)
|
||||
{
|
||||
Log.getLogger().error($"Failed to TryAdd() !!!, Already added CommandKey !!! : commandKey:{command_key}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool isCheatCommand(string input)
|
||||
{
|
||||
return input.StartsWith("//");
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> HandleCommand(Player player, string input)
|
||||
{
|
||||
var tokenArr = input.Split(" ", 2);
|
||||
|
||||
try
|
||||
{
|
||||
var command = tokenArr[0].Remove(0, 2);
|
||||
|
||||
if (command_base_map.TryGetValue(command.ToLower(), out var handler_class) == false)
|
||||
{
|
||||
Log.getLogger().error($"Command Not Exist Command : {command.ToLower()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (await hasAuthority(handler_class, player) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tokenArr.Length > 1)
|
||||
{
|
||||
var args = tokenArr[1].Split(" ", StringSplitOptions.RemoveEmptyEntries);
|
||||
await handler_class.invoke(player, tokenArr[1], args);
|
||||
}
|
||||
else
|
||||
{
|
||||
await handler_class.invoke(player, String.Empty, new string[] { });
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException e)
|
||||
{
|
||||
Log.getLogger().error($"TaskCanceledException !!!, Failed to perform in HandleCommand() !!! : exception:{e}, inputString:{input} - {player.toBasicString()}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.getLogger().error($"Exception !!!, Failed to perform in HandleCommand() !!! : exception:{e}, inputString:{input} - {player.toBasicString()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> hasAuthority(ChatCommandBase handlerClass, Player player)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var server_config = ServerConfigHelper.getServerConfig();
|
||||
NullReferenceCheckHelper.throwIfNull(server_config, () => $"server_config is null !!!");
|
||||
|
||||
// ServiceType.Dev 타입일 경우 무조건 치트 사용이 가능 하다. !!!
|
||||
if (server_config.ServiceType.Equals(ServiceType.Dev.ToString()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// CheatCommandAlwaysAllow == true 일 경우 무조건 치트 사용이 가능 하다. !!!
|
||||
if (true == server_config.CheatCommandAlwaysAllow)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var account_attribute = player.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!!");
|
||||
|
||||
var admin_level_type = account_attribute.AuthAdminLevelType;
|
||||
//여기에 유저 레벨이랑, 클래스에 할당된 레벨이랑 비교 필요
|
||||
var class_admin_level_type = handlerClass.getAuthAddminLevelType();
|
||||
|
||||
if (class_admin_level_type.Contains(admin_level_type) == false)
|
||||
{
|
||||
Log.getLogger().info($"Not Match Admin LevelType !!! : className = {handlerClass.getAuthAddminLevelType().ToString()}, className:{handlerClass.getClassName()} - {player.toBasicString()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
internal class ChatCommandAttribute : Attribute
|
||||
{
|
||||
readonly string m_cheat_comment;
|
||||
private readonly Type m_handler_class;
|
||||
private readonly HashSet<AuthAdminLevelType> m_auth_admin_level_type;
|
||||
|
||||
public ChatCommandAttribute(string cheatCommend, Type handlerClass, params AuthAdminLevelType[] authAdminLevelType)
|
||||
{
|
||||
m_cheat_comment = cheatCommend;
|
||||
m_handler_class = handlerClass;
|
||||
m_auth_admin_level_type = new HashSet<AuthAdminLevelType>(authAdminLevelType);
|
||||
}
|
||||
|
||||
public string getCommand()
|
||||
{
|
||||
return m_cheat_comment;
|
||||
}
|
||||
|
||||
public HashSet<AuthAdminLevelType> getAdminLevel()
|
||||
{
|
||||
return m_auth_admin_level_type;
|
||||
}
|
||||
|
||||
public Type getHandlerClass()
|
||||
{
|
||||
return m_handler_class;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ChatCommandBase
|
||||
{
|
||||
private HashSet<AuthAdminLevelType> m_auth_admin_level_type = new();
|
||||
private string m_class_name = string.Empty;
|
||||
|
||||
public void setAuthAdminLevelType(HashSet<AuthAdminLevelType> typeSet)
|
||||
{
|
||||
m_auth_admin_level_type = typeSet;
|
||||
}
|
||||
|
||||
public HashSet<AuthAdminLevelType> getAuthAddminLevelType()
|
||||
{
|
||||
return m_auth_admin_level_type;
|
||||
}
|
||||
|
||||
|
||||
public void setClassName(string className)
|
||||
{
|
||||
m_class_name = className;
|
||||
}
|
||||
|
||||
public string getClassName()
|
||||
{
|
||||
return m_class_name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("sessionkeepalivetime", typeof(ChatCommandSessionKeepAliveTime), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class ChatCommandSessionKeepAliveTime : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
Log.getLogger().info($"Call sessionkeepalivetime !!! - {player.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 3 - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
var keep_alive_minutes = int.Parse(args[0]);
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
||||
|
||||
|
||||
var session = player as IEntityWithSession;
|
||||
NullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!! - {player.toBasicString()}");
|
||||
|
||||
var timeout_ms = keep_alive_minutes * ConstValue.default_1_min_to_sec * ConstValue.default_1_sec_to_milisec;
|
||||
|
||||
var net_server = server_logic.getProudNetListener().getNetServer();
|
||||
NullReferenceCheckHelper.throwIfNull(net_server, () => $"net_server is null !!!");
|
||||
net_server.SetTimeoutTimeMs(session.getHostId(), timeout_ms);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using GameServer.PacketHandler;
|
||||
|
||||
|
||||
namespace GameServer.ChatCommandHandler;
|
||||
|
||||
[ChatCommandAttribute("warp", typeof(WarpCommandHandler), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class WarpCommandHandler : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
if (args.Length < 1) return;
|
||||
if (!int.TryParse(args[0], out var warp_id)) return;
|
||||
|
||||
var result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CheetWarp", warpDelegate);
|
||||
if (result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to runTransactionRunnerSafely : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
async Task<Result> warpDelegate() => await warpAsync(player, warp_id);
|
||||
}
|
||||
|
||||
private async Task<Result> warpAsync(Player player, int warpId)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var res = new ClientToGameRes.Types.WarpRes();
|
||||
|
||||
var game_zone_move_action = player.getEntityAction<GameZoneMoveAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_move_action, () => $"game_zone_move_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, res, var business_logs) = await game_zone_move_action.tryWarp(warpId);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to tryWarp() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
WarpPacketHandler.send_S2C_ACK_WARP(player, result, res);
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(business_logs, () => $"business_logs is null !!! - warpId:{warpId}, {player.toBasicString()}");
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.Warp, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
batch.addQuery(new QueryFinal());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(business_logs);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
WarpPacketHandler.send_S2C_ACK_WARP(player, result, res);
|
||||
return result;
|
||||
}
|
||||
|
||||
WarpPacketHandler.send_S2C_ACK_WARP(player, result, res);
|
||||
if (res.PlaceCase == ClientToGameRes.Types.WarpRes.PlaceOneofCase.Pos)
|
||||
{
|
||||
player.send_S2C_NTF_SET_LOCATION();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
32
GameServer/Contents/Chat/Log/ChatBusinessLog.cs
Normal file
32
GameServer/Contents/Chat/Log/ChatBusinessLog.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class ChatBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private ChatLogData m_data_to_log;
|
||||
public ChatBusinessLog(ChatLogData log_data_param)
|
||||
: base(LogDomainType.Chat)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new ChatLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
39
GameServer/Contents/Chat/Log/ChatBusinessLogHelper.cs
Normal file
39
GameServer/Contents/Chat/Log/ChatBusinessLogHelper.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public static class ChatBusinessLogHelper
|
||||
{
|
||||
static public ChatLogData toLogInfo(string chatMessage, CellPos cellpos)
|
||||
{
|
||||
var logData = new ChatLogData();
|
||||
logData.setInfo(chatMessage, cellpos);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public ChatLogData toLogInfo(string chatMessage, string targetUser = "")
|
||||
{
|
||||
var logData = new ChatLogData();
|
||||
logData.setInfo(chatMessage, targetUser);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this ChatLogData logData, string chatMessage, string targetUser)
|
||||
{
|
||||
logData.TargetUser = targetUser;
|
||||
logData.ChatMessage = chatMessage;
|
||||
}
|
||||
|
||||
static public void setInfo(this ChatLogData logData, string chatMessage, CellPos cellpos)
|
||||
{
|
||||
logData.ChatMessage = chatMessage;
|
||||
logData.cellPosX = cellpos.CellX;
|
||||
logData.cellPosX = cellpos.CellY;
|
||||
}
|
||||
}
|
||||
81
GameServer/Contents/Chat/PacketHandler/ChatNotifyHelper.cs
Normal file
81
GameServer/Contents/Chat/PacketHandler/ChatNotifyHelper.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using ServerCore; using ServerBase;
|
||||
using static ServerMessage.Types;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class ChatNotifyHelper
|
||||
{
|
||||
|
||||
public static ClientToGame makeChatMessage(ChatType chat_type, string sender_nickname, string receiver_nickname, PlayerStateType receiver_state, string message)
|
||||
{
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.Chat = new();
|
||||
|
||||
noti_packet.Message.Chat.Type = chat_type;
|
||||
noti_packet.Message.Chat.Sender = sender_nickname;
|
||||
noti_packet.Message.Chat.Receiver = receiver_nickname;
|
||||
noti_packet.Message.Chat.Receiverstate = receiver_state;
|
||||
noti_packet.Message.Chat.Message = message;
|
||||
|
||||
return noti_packet;
|
||||
}
|
||||
|
||||
public static bool send_S2C_NTF_CHAT(Player player, ChatType chat_type, string sender_nickname, string receiver_nickname, PlayerStateType receiver_state, string message)
|
||||
{
|
||||
var noti_packet = makeChatMessage(chat_type, sender_nickname, receiver_nickname, receiver_state, message);
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, noti_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool send_S2C_NTF_CHAT_BROADCAST(Player player, ChatType chat_type, string sender_nickname, string receiver_nickname, PlayerStateType receiver_state, string message)
|
||||
{
|
||||
var noti_packet = makeChatMessage(chat_type, sender_nickname, receiver_nickname, receiver_state, message);
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
game_zone_action.broadcast(player, noti_packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void send_S2C_NTF_MQ_CHAT(Chat chat)
|
||||
{
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var player_manager = server_logic.getPlayerManager();
|
||||
|
||||
switch (chat.Type)
|
||||
{
|
||||
case ChatType.Notice:
|
||||
{
|
||||
var players = player_manager.getUsers();
|
||||
foreach (var player in players)
|
||||
{
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(player.Value, chat.Type, chat.SenderNickName, "", PlayerStateType.None, chat.Message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ChatType.Whisper:
|
||||
{
|
||||
if (player_manager.tryGetUserByPrimaryKey(chat.ReceiverGuid, out var found_user) == false) return;
|
||||
if (found_user == null) return;
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(found_user, chat.Type, chat.SenderNickName, found_user.getUserNickname(), PlayerStateType.None, chat.Message);
|
||||
break;
|
||||
}
|
||||
case ChatType.Party:
|
||||
{
|
||||
//await PartyManager.Instance.ChatBroadcast(chat.Receiver, clientToGame);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
180
GameServer/Contents/Chat/PacketHandler/ChatPacketHandler.cs
Normal file
180
GameServer/Contents/Chat/PacketHandler/ChatPacketHandler.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.ChatReq), typeof(ChatPacketHandler), typeof(GameLoginListener))]
|
||||
public class ChatPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_CHAT(Player player, Result result, string receiver_nickname, ChatType chat_type = ChatType.None, string sender_nickname = "", string receiver_guid = "", PlayerStateType receiver_state = PlayerStateType.None, string message = "")
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.ChatRes = new ChatRes();
|
||||
|
||||
ack_packet.Response.ChatRes.Type = chat_type;
|
||||
ack_packet.Response.ChatRes.Sender = sender_nickname;
|
||||
ack_packet.Response.ChatRes.Receiver = receiver_nickname;
|
||||
ack_packet.Response.ChatRes.Receiverid = receiver_guid;
|
||||
ack_packet.Response.ChatRes.Receiverstate = receiver_state;
|
||||
ack_packet.Response.ChatRes.Message = message;
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var chat_action = entity_player.getEntityAction<ChatAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(chat_action, () => $"chat_action is null !!!");
|
||||
|
||||
// 1. 메시지 체크
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ChatReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_CHAT(entity_player, result, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ChatReq;
|
||||
|
||||
// 2. 유저 block 체크
|
||||
var account_attribute = entity_player.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {entity_player.toBasicString()}");
|
||||
var account_base_doc = account_attribute.getOriginDocBase<AccountAttribute>() as AccountBaseDoc;
|
||||
NullReferenceCheckHelper.throwIfNull(account_base_doc, () => $"account_base_doc is null !!!");
|
||||
|
||||
var doc_account_base_attrib = account_base_doc.getAttrib<AccountBaseAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(doc_account_base_attrib, () => $"doc_account_base_attrib is null !!!");
|
||||
|
||||
var block_policy = UserBlockHelper.convertBlockPolicyToJavaPolicy(doc_account_base_attrib.BlockPolicy);
|
||||
if (block_policy.Contains(UserBlockPolicyType.ChattingRestrictions.ToString()))
|
||||
{
|
||||
//여기서 강제로 리턴
|
||||
send_S2C_ACK_CHAT(entity_player, result, request.ToNickName);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 3. cheat 체크
|
||||
if (server_logic.ChatCommand.isCheatCommand(request.Message) == true)
|
||||
{
|
||||
await server_logic.ChatCommand.HandleCommand(entity_player, request.Message);
|
||||
send_S2C_ACK_CHAT(entity_player, result, request.ToNickName);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 4. chat 기본 조건 체크
|
||||
result = checkChatConditions(request.Message);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_CHAT(entity_player, result, request.ToNickName);
|
||||
return result;
|
||||
}
|
||||
|
||||
var chat_type = request.Type;
|
||||
|
||||
// 5. 채팅 처리
|
||||
switch (chat_type)
|
||||
{
|
||||
case ChatType.Normal:
|
||||
result = chat_action.NormalChat(request.Message);
|
||||
break;
|
||||
case ChatType.Channel:
|
||||
result = chat_action.ChannelChat(request.Message);
|
||||
break;
|
||||
case ChatType.Notice:
|
||||
result = chat_action.NoticeChat(request.Message);
|
||||
break;
|
||||
case ChatType.Whisper:
|
||||
result = await chat_action.WhisperChat(request.ToNickName, request.Message);
|
||||
break;
|
||||
case ChatType.Party:
|
||||
result = await chat_action.PartyChat(request.Message);
|
||||
break;
|
||||
default:
|
||||
err_msg = $"Invalid EChatType !!! EChatType : {request.Type} - {entity_player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ChatInvalidChatType, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to trySendMail() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
await QuestManager.It.QuestCheck(entity_player, new QuestChat(EQuestEventTargetType.CHAT, EQuestEventNameType.USED, chat_type.ToString(), request.Message));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result checkChatConditions(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
// 1. 총 길이 체크
|
||||
if (message.Length > MetaHelper.GameConfigMeta.ChatStringInputMax)
|
||||
{
|
||||
err_msg = $"fail to send chat !!! : invalid chat message length - {message.Length}";
|
||||
result.setFail(ServerErrorCode.ChatInvalidMessageLength, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 금칙어 체크 ( Client 에서 처리함 )
|
||||
/*if (ServerUtil.isBanWorld(message, false))
|
||||
{
|
||||
err_msg = $"fail to send chat !!! : include ban word - {message}";
|
||||
result.setFail(ServerErrorCode.ChatIncludeBanWord, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
|
||||
var request = recv_msg.Request.ChatReq;
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_CHAT(player, errorResult, request.ToNickName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Newtonsoft.Json;
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
|
||||
public class RabbitNoticeChatHandler
|
||||
{
|
||||
public void MOS2GS_noticeChatSend(ServerMessage.Types.MOS2GS_NTF_NOTICE_CHAT chatMsg)
|
||||
{
|
||||
//OperationSystemNoticeChatType
|
||||
|
||||
Log.getLogger().debug("MOS2GS_noticeChatSend call start");
|
||||
// 1. 메시지 체크
|
||||
if (chatMsg == null)
|
||||
{
|
||||
var err_msg = $"chatMsg is null !!! : {nameof(ServerMessage.Types.MOS2GS_NTF_NOTICE_CHAT)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
//await server_logic.getNoticeChatManager().LoadDB();
|
||||
var notice_type = chatMsg.NoticeType.ToString();
|
||||
var chat_msgs = chatMsg.ChatMessage;
|
||||
var senders = chatMsg.Sender;
|
||||
|
||||
Dictionary<int, string> dic_msg_by_lang = new();
|
||||
Dictionary<int, string> dic_sender_by_lang = new();
|
||||
foreach(var chat_msg in chat_msgs)
|
||||
{
|
||||
var txt = StringRuleHelper.convertStringFromBase64(chat_msg.Text);
|
||||
dic_msg_by_lang.Add((int)chat_msg.LanguageType, txt);
|
||||
}
|
||||
|
||||
foreach(var sender in senders)
|
||||
{
|
||||
var sender_txt = StringRuleHelper.convertStringFromBase64(sender.Text);
|
||||
dic_sender_by_lang.Add((int)sender.LanguageType, sender_txt);
|
||||
}
|
||||
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var player_manager = server_logic.getPlayerManager();
|
||||
// if (notice_type.Equals(OperationSystemNoticeChatType.CHATTING.ToString()))
|
||||
// {
|
||||
|
||||
//일단 채팅이든 토스트든 전부 notice로 전달한다.
|
||||
var users = player_manager.getUsers();
|
||||
foreach (var user in users)
|
||||
{
|
||||
var player = user.Value;
|
||||
var account_attribute = player.getEntityAttribute<AccountAttribute>();
|
||||
if(account_attribute == null) continue;
|
||||
|
||||
if(dic_msg_by_lang.TryGetValue((int)account_attribute.LanguageType, out var chat_msg) == false)
|
||||
{
|
||||
var err_msg = $"dic_msg_by_lang error accountid : {account_attribute.AccountId}, langtype : {account_attribute.LanguageType}, {JsonConvert.SerializeObject(dic_msg_by_lang)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dic_sender_by_lang.TryGetValue((int)account_attribute.LanguageType, out var sender) == false)
|
||||
{
|
||||
var err_msg = $"dic_sender_by_lang error accountid : {account_attribute.AccountId}, langtype : {account_attribute.LanguageType}, {JsonConvert.SerializeObject(dic_sender_by_lang)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(player, ChatType.Notice, sender, player.getUserNickname(), PlayerStateType.None, chat_msg);
|
||||
}
|
||||
|
||||
Log.getLogger().debug($"MOS2GS_noticeChatSend call end userCount = {users.Count}, lang_msg : {JsonConvert.SerializeObject(dic_msg_by_lang)}, sender_msg : {JsonConvert.SerializeObject(dic_sender_by_lang)}");
|
||||
|
||||
// }
|
||||
// else if (notice_type.Equals(OperationSystemNoticeChatType.CHATTING_TOAST.ToString()))
|
||||
// {
|
||||
// var err_msg = $"CHATTING_TOAST not implement !!!";
|
||||
// return;
|
||||
// }
|
||||
|
||||
//메시지에 대한 필터링을 어떻게 해야하지?
|
||||
// 4. 채팅 처리
|
||||
// switch (chat_type)
|
||||
// {
|
||||
// case ChatType.Normal:
|
||||
// result = chat_action.NormalChat(request.Message);
|
||||
// break;
|
||||
// case ChatType.Channel:
|
||||
// result = chat_action.ChannelChat(request.Message);
|
||||
// break;
|
||||
// case ChatType.Notice:
|
||||
//result = chat_action.NoticeChat(request.Message);
|
||||
// break;
|
||||
// case ChatType.Whisper:
|
||||
// result = await chat_action.WhisperChat(request.ToNickName, request.Message);
|
||||
// break;
|
||||
// case ChatType.Party:
|
||||
// result = await chat_action.PartyChat(request.Message);
|
||||
// break;
|
||||
// if (result.isFail())
|
||||
// {
|
||||
// err_msg = $"Failed to trySendMail() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
// Log.getLogger().error(err_msg);
|
||||
// return result;
|
||||
// }
|
||||
// return result;
|
||||
}
|
||||
}
|
||||
592
GameServer/Contents/Claim/Action/ClaimAction.cs
Normal file
592
GameServer/Contents/Claim/Action/ClaimAction.cs
Normal file
@@ -0,0 +1,592 @@
|
||||
using Amazon.S3.Model;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using RabbitMQ.Client;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class ClaimAction : EntityActionBase
|
||||
{
|
||||
private ConcurrentDictionary<Int32, ServerCommon.Claim> m_normal_claim { get; set; } = new();
|
||||
private ConcurrentDictionary<Int32, ServerCommon.Claim> m_membership_claim { get; set; } = new();
|
||||
|
||||
private bool m_data_load = false;
|
||||
|
||||
public ClaimAction(EntityBase owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
|
||||
public void setDataLoad(bool isLoad)
|
||||
{
|
||||
m_data_load = isLoad;
|
||||
}
|
||||
public bool getDataLoad()
|
||||
{
|
||||
return m_data_load;
|
||||
}
|
||||
|
||||
|
||||
public Result setClaimFromDoc(ClaimDoc doc)
|
||||
{
|
||||
var result = new Result();
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
EntityBase claim;
|
||||
|
||||
var claim_attrib = doc.getAttrib<ClaimAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_attrib, () => $"claim_attrib is null !!!");
|
||||
claim = new ServerCommon.Claim(owner, claim_attrib.ClaimType);
|
||||
|
||||
var claim_attribute = claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_attribute, () => $"claim_attribute is null !!!");
|
||||
|
||||
if (false == doc.getAttribWrappers().TryGetValue(typeof(ClaimAttrib), out var to_copy_doc_attrib))
|
||||
{
|
||||
var err_msg = $"Fail to get ClaimAttrib";
|
||||
result.setFail(ServerErrorCode.EntityAttributeNotFound, err_msg);
|
||||
return result;
|
||||
}
|
||||
var attrib_base = to_copy_doc_attrib.getAttribBase();
|
||||
var doc_attrib = attrib_base as ClaimAttrib;
|
||||
if (doc_attrib is null)
|
||||
{
|
||||
var err_msg = $"Fail to get ClaimAttrib";
|
||||
result.setFail(ServerErrorCode.EntityAttributeNotFound, err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
claim_attribute.ClaimType = doc_attrib.ClaimType;
|
||||
claim_attribute.ActiveRewardIdx = doc_attrib.ActiveRewardIdx;
|
||||
claim_attribute.ActiveTime = doc_attrib.ActiveTime;
|
||||
claim_attribute.CreateTime = doc_attrib.CreateTime;
|
||||
claim_attribute.CompleteTime = doc_attrib.CompleteTime;
|
||||
claim_attribute.IsComplete = doc_attrib.IsComplete;
|
||||
|
||||
claim_attribute.syncOriginDocBaseWithNewDoc<ClaimAttribute>(doc);
|
||||
|
||||
Int32 claim_id = claim_attribute.ClaimId = doc_attrib.ClaimId;
|
||||
|
||||
var casted_claim = claim as ServerCommon.Claim;
|
||||
NullReferenceCheckHelper.throwIfNull(casted_claim, () => $"casted_claim is null !!!");
|
||||
if (claim_attrib.ClaimType == MetaAssets.ClaimType.Normal)
|
||||
{
|
||||
m_normal_claim.TryAdd(claim_id, casted_claim);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_membership_claim.TryAdd(claim_id, casted_claim);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public async Task<(Result, List<ClaimMetaData>, List<Int32>)> update()
|
||||
{
|
||||
var result = new Result();
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
(var acceptable_claims, var old_claims) = getUpdatableClaims();
|
||||
if (acceptable_claims.Count == 0 && old_claims.Count == 0) return (result, new(), new());
|
||||
|
||||
result = await owner.runTransactionRunnerSafelyWithTransGuid( owner.getUserGuid()
|
||||
, TransactionIdType.PrivateContents, "ClaimUpdate", delegateUpdateClaim);
|
||||
if (result.isFail())
|
||||
{
|
||||
string err_msg = $"Failed to runTransactionRunnerSafelyWithTransGuid() !!! : {result.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, new(), new());
|
||||
}
|
||||
return (result, acceptable_claims, old_claims);
|
||||
|
||||
async Task<Result> delegateUpdateClaim() => await updateClaim(owner, acceptable_claims, old_claims);
|
||||
|
||||
}
|
||||
|
||||
public (List<ClaimMetaData>, List<Int32>) getUpdatableClaims()
|
||||
{
|
||||
var acceptable_claims = getAcceptableClaims();
|
||||
var old_claims = getOldClaim();
|
||||
return (acceptable_claims, old_claims);
|
||||
}
|
||||
|
||||
public static List<ClaimMetaData> getOldClaims()
|
||||
{
|
||||
List<ClaimMetaData> rets = new();
|
||||
DateTime nowDt = DateTimeHelper.Current;
|
||||
|
||||
foreach (ClaimMetaData metaData in MetaData.Instance._ClaimMetaTable.Values)
|
||||
{
|
||||
if (metaData.EndTime < nowDt)
|
||||
{
|
||||
rets.Add(metaData);
|
||||
}
|
||||
}
|
||||
return rets;
|
||||
}
|
||||
|
||||
private async Task<Result> updateClaim(Player owner, List<ClaimMetaData> acceptableClaim, List<Int32> oldClaim)
|
||||
{
|
||||
(var result, var new_claims) = updateClaims(acceptableClaim, oldClaim);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(owner, LogActionType.None, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var new_claim in new_claims)
|
||||
{
|
||||
var claim_attribute = new_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_attribute, () => $"claim_attribute is null !!!");
|
||||
|
||||
if (claim_attribute.ClaimType == MetaAssets.ClaimType.Normal)
|
||||
{
|
||||
m_normal_claim.TryAdd(claim_attribute.ClaimId, new_claim as ServerCommon.Claim);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_membership_claim.TryAdd(claim_attribute.ClaimId, new_claim as ServerCommon.Claim);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var old_claim in oldClaim)
|
||||
{
|
||||
m_normal_claim.TryRemove(old_claim, out _);
|
||||
m_membership_claim.TryRemove(old_claim, out _);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private (Result, List<ServerCommon.Claim>) updateClaims(List<ClaimMetaData> acceptable_claims, List<Int32> oldClaims)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
DateTime now = DateTimeHelper.Current;
|
||||
List<ServerCommon.Claim> claims = new();
|
||||
|
||||
foreach (var meta in acceptable_claims)
|
||||
{
|
||||
var claim_id = meta.ClaimId;
|
||||
var claim_type = meta.ClaimType;
|
||||
|
||||
if (claim_type == MetaAssets.ClaimType.Normal)
|
||||
{
|
||||
if (m_normal_claim.ContainsKey(claim_id)) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_membership_claim.ContainsKey(claim_id)) continue;
|
||||
}
|
||||
|
||||
var new_claim = makeNewClaim(now, meta);
|
||||
claims.Add(new_claim);
|
||||
//m_normal_claim.TryAdd(claim_id, normal_claim);
|
||||
}
|
||||
|
||||
foreach (var old_claim in oldClaims)
|
||||
{
|
||||
if (false == m_normal_claim.TryGetValue(old_claim, out var normal_claim)) continue;
|
||||
NullReferenceCheckHelper.throwIfNull(normal_claim, () => $"normal_claim is null !!!");
|
||||
var normal_claim_attribute = normal_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(normal_claim_attribute, () => $"normal_claim_attribute is null !!!");
|
||||
normal_claim_attribute.deleteEntityAttribute();
|
||||
}
|
||||
foreach (var old_claim in oldClaims)
|
||||
{
|
||||
if (false == m_membership_claim.TryGetValue(old_claim, out var membership_claim)) continue;
|
||||
NullReferenceCheckHelper.throwIfNull(membership_claim, () => $"membership_claim is null !!!");
|
||||
var membership_claim_attribute = membership_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(membership_claim_attribute, () => $"membership_claim_attribute is null !!!");
|
||||
membership_claim_attribute.deleteEntityAttribute();
|
||||
}
|
||||
|
||||
return (result, claims);
|
||||
}
|
||||
|
||||
private ServerCommon.Claim resetClaim(ServerCommon.Claim claim, ClaimMetaData metaData)
|
||||
{
|
||||
var owner = getOwner() as Player;
|
||||
|
||||
DateTime now = DateTimeHelper.Current;
|
||||
var claim_attribute = claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_attribute, () => $"claim_attribute is null !!!");
|
||||
claim_attribute.ActiveRewardIdx = metaData.DetailInfo.First().Value.Idx;
|
||||
claim_attribute.ActiveTime = now;
|
||||
claim_attribute.CreateTime = now;
|
||||
claim_attribute.CompleteTime = now;
|
||||
claim_attribute.IsComplete = 0;
|
||||
claim_attribute.modifiedEntityAttribute();
|
||||
|
||||
return claim;
|
||||
}
|
||||
|
||||
private ServerCommon.Claim updateClaimRewardable(ServerCommon.Claim claim, ClaimMetaData metaData)
|
||||
{
|
||||
var owner = getOwner() as Player;
|
||||
|
||||
DateTime now = DateTimeHelper.Current;
|
||||
|
||||
var claim_attribute = claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_attribute, () => $"claim_attribute is null !!!");
|
||||
claim_attribute.ActiveTime = now.AddSeconds(-86400);
|
||||
claim_attribute.modifiedEntityAttribute();
|
||||
|
||||
return claim;
|
||||
}
|
||||
|
||||
private ServerCommon.Claim makeNewClaim(DateTime now, ClaimMetaData metaData)
|
||||
{
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
var claim = new ServerCommon.Claim(getOwner(), metaData.ClaimType);
|
||||
|
||||
var claim_attribute = claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_attribute, () => $"claim_attribute is null !!!");
|
||||
|
||||
claim_attribute.ClaimId = metaData.ClaimId;
|
||||
claim_attribute.ClaimType = metaData.ClaimType;
|
||||
claim_attribute.ActiveRewardIdx = metaData.DetailInfo.First().Value.Idx;
|
||||
claim_attribute.ActiveTime = now;
|
||||
claim_attribute.CreateTime = now;
|
||||
claim_attribute.CompleteTime = now;
|
||||
claim_attribute.IsComplete = 0;
|
||||
|
||||
var new_claim_doc = new ClaimDoc(owner.getUserGuid(), metaData.ClaimType, metaData.ClaimId);
|
||||
claim_attribute.syncOriginDocBaseWithNewDoc<ClaimAttribute>(new_claim_doc);
|
||||
|
||||
var claim_attrib = new_claim_doc.getAttrib<ClaimAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_attrib, () => $"claim_attrib is null !!!");
|
||||
|
||||
claim_attrib.ClaimId = metaData.ClaimId;
|
||||
claim_attrib.ClaimType = metaData.ClaimType;
|
||||
claim_attrib.ActiveRewardIdx = metaData.DetailInfo.First().Value.Idx;
|
||||
claim_attrib.ActiveTime = now;
|
||||
claim_attrib.CreateTime = now;
|
||||
claim_attrib.CompleteTime = now;
|
||||
claim_attrib.IsComplete = 0;
|
||||
|
||||
claim_attribute.newEntityAttribute();
|
||||
|
||||
return claim;
|
||||
}
|
||||
|
||||
|
||||
private List<ClaimMetaData> getAcceptableClaims()
|
||||
{
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
List<ClaimMetaData> rets = new();
|
||||
|
||||
var current_metas = ClaimRewardHelper.getCurrentClaims();
|
||||
|
||||
foreach (var metaData in current_metas)
|
||||
{
|
||||
var claim_id = metaData.GetMetaId();
|
||||
if (m_normal_claim.ContainsKey(claim_id)) continue;
|
||||
rets.Add(metaData);
|
||||
}
|
||||
return rets;
|
||||
}
|
||||
|
||||
public List<Int32> getOldClaim()
|
||||
{
|
||||
List<ClaimMetaData> old_metas = getOldClaims();
|
||||
List<Int32> old_claims = new();
|
||||
|
||||
foreach (var meta in old_metas)
|
||||
{
|
||||
var claim_id = meta.ClaimId;
|
||||
if (m_normal_claim.ContainsKey(claim_id))
|
||||
{
|
||||
old_claims.Add(claim_id);
|
||||
}
|
||||
}
|
||||
|
||||
return old_claims;
|
||||
}
|
||||
|
||||
|
||||
public async Task cheatClaimReset()
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var result = new Result();
|
||||
|
||||
|
||||
var fn_reset_claim = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
List<ILogInvoker> log_invokers = new();
|
||||
|
||||
foreach (var normal_claim in m_normal_claim.Values)
|
||||
{
|
||||
var normal_claim_attribute = normal_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(normal_claim_attribute, () => $"normal_claim_attribute is null !!!");
|
||||
var claim_id = normal_claim_attribute.ClaimId;
|
||||
(result, var claim_meta) = ClaimRewardHelper.getClaimMeta(claim_id, MetaAssets.ClaimType.Normal);
|
||||
if (result.isFail())continue;
|
||||
NullReferenceCheckHelper.throwIfNull(claim_meta, () => $"claim_meta is null !!!");
|
||||
resetClaim(normal_claim, claim_meta);
|
||||
|
||||
var log_invoker = new CheatClaimResetBusinessLog(MetaAssets.ClaimType.Normal, claim_id, normal_claim_attribute.ActiveRewardIdx);
|
||||
log_invokers.Add(log_invoker);
|
||||
}
|
||||
|
||||
foreach (var membership_claim in m_membership_claim.Values)
|
||||
{
|
||||
var membership_claim_attribute = membership_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(membership_claim_attribute, () => $"normal_claim_attribute is null !!!");
|
||||
var claim_id = membership_claim_attribute.ClaimId;
|
||||
(result, var claim_meta) = ClaimRewardHelper.getClaimMeta(claim_id, MetaAssets.ClaimType.Membership);
|
||||
if (result.isFail()) continue;
|
||||
NullReferenceCheckHelper.throwIfNull(claim_meta, () => $"claim_meta is null !!!");
|
||||
resetClaim(membership_claim, claim_meta);
|
||||
|
||||
var log_invoker = new CheatClaimResetBusinessLog(MetaAssets.ClaimType.Membership, claim_id, membership_claim_attribute.ActiveRewardIdx);
|
||||
log_invokers.Add(log_invoker);
|
||||
}
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CheatCommandClaimReset, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
foreach (var normal_claim in m_normal_claim.Values)
|
||||
{
|
||||
var normal_claim_attribute = normal_claim.getEntityAttribute<ClaimAttribute>();
|
||||
if (normal_claim_attribute is null) continue;
|
||||
|
||||
var claim_id = normal_claim_attribute.ClaimId;
|
||||
|
||||
}
|
||||
send_GS2C_NTF_CLAIM_UPDATE();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CheatResetClaim", fn_reset_claim);
|
||||
if (result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task cheatClaimUpdateRewardable()
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"server_logic is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var result = new Result();
|
||||
|
||||
var fn_claim_update_rewardable = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
List<ILogInvoker> log_invokers = new();
|
||||
foreach (var normal_claim in m_normal_claim.Values)
|
||||
{
|
||||
var normal_claim_attribute = normal_claim.getEntityAttribute<ClaimAttribute>();
|
||||
if (normal_claim_attribute is null) continue;
|
||||
var claim_id = normal_claim_attribute.ClaimId;
|
||||
(result, var claim_meta) = ClaimRewardHelper.getClaimMeta(claim_id, MetaAssets.ClaimType.Normal);
|
||||
if (result.isFail()) continue;
|
||||
NullReferenceCheckHelper.throwIfNull(claim_meta, () => $"claim_meta is null !!!");
|
||||
updateClaimRewardable(normal_claim, claim_meta);
|
||||
|
||||
var log_invoker = new CheatClaimRewardableBusinessLog(MetaAssets.ClaimType.Normal, claim_id, normal_claim_attribute.ActiveRewardIdx);
|
||||
log_invokers.Add(log_invoker);
|
||||
}
|
||||
|
||||
foreach (var membership_claim in m_membership_claim.Values)
|
||||
{
|
||||
var membership_claim_attribute = membership_claim.getEntityAttribute<ClaimAttribute>();
|
||||
if (membership_claim_attribute is null) continue;
|
||||
var claim_id = membership_claim_attribute.ClaimId;
|
||||
(result, var claim_meta) = ClaimRewardHelper.getClaimMeta(claim_id, MetaAssets.ClaimType.Membership);
|
||||
if (result.isFail()) continue;
|
||||
NullReferenceCheckHelper.throwIfNull(claim_meta, () => $"claim_meta is null !!!");
|
||||
updateClaimRewardable(membership_claim, claim_meta);
|
||||
var log_invoker = new CheatClaimRewardableBusinessLog(MetaAssets.ClaimType.Membership, claim_id, membership_claim_attribute.ActiveRewardIdx);
|
||||
log_invokers.Add(log_invoker);
|
||||
}
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CheatCommandClaimUpdate, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
batch.appendBusinessLogs(log_invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var normal_claim in m_normal_claim.Values)
|
||||
{
|
||||
var normal_claim_attribute = normal_claim.getEntityAttribute<ClaimAttribute>();
|
||||
if(normal_claim_attribute is null) continue;
|
||||
var claim_id = normal_claim_attribute.ClaimId;
|
||||
|
||||
}
|
||||
send_GS2C_NTF_CLAIM_UPDATE();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CheatClaimUpdateRewardable", fn_claim_update_rewardable);
|
||||
if (result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<Int32, ServerCommon.Claim> getClaims(MetaAssets.ClaimType type)
|
||||
{
|
||||
if (type == MetaAssets.ClaimType.Normal)
|
||||
{
|
||||
|
||||
return m_normal_claim;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_membership_claim;
|
||||
}
|
||||
}
|
||||
|
||||
public Result getClaim(Int32 claimId, MetaAssets.ClaimType type, [MaybeNullWhen(false)] out ServerCommon.Claim? claim)
|
||||
{
|
||||
var result = new Result();
|
||||
if (type == MetaAssets.ClaimType.Normal)
|
||||
{
|
||||
|
||||
result = getNormalClaim(claimId, out claim);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = getMembershipClaim(claimId, out claim);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<Int32, ServerCommon.Claim> getNormalClaims()
|
||||
{
|
||||
return m_normal_claim;
|
||||
}
|
||||
|
||||
public Result getNormalClaim(Int32 claimId, [MaybeNullWhen(false)] out ServerCommon.Claim? claim)
|
||||
{
|
||||
var result = new Result();
|
||||
if (false == m_normal_claim.TryGetValue(claimId, out claim))
|
||||
{
|
||||
var err_msg = $"m_normal_claim claimId : {claimId} not exist, {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ClaimInfoNotExist, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(claim, () => $"claim is null !!!");
|
||||
return result;
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<Int32, ServerCommon.Claim> getMembershipClaims()
|
||||
{
|
||||
return m_membership_claim;
|
||||
}
|
||||
|
||||
public Result getMembershipClaim(Int32 claimId, [MaybeNullWhen(false)] out ServerCommon.Claim? claim)
|
||||
{
|
||||
var result = new Result();
|
||||
if (false == m_membership_claim.TryGetValue(claimId, out claim))
|
||||
{
|
||||
var err_msg = $"m_membership_claim claimId : {claimId} not exist, {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ClaimInfoNotExist, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(claim, () => $"claim is null !!!");
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public void send_GS2C_NTF_CLAIM_UPDATE()
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!!");
|
||||
|
||||
var normal_claim_infos = ClaimRewardHelper.MakeClaimSendInfo(player, MetaAssets.ClaimType.Normal);
|
||||
var membership_claim_infos = ClaimRewardHelper.MakeClaimSendInfo(player, MetaAssets.ClaimType.Membership);
|
||||
|
||||
foreach (var info in normal_claim_infos)
|
||||
{
|
||||
ClientToGame ntf_packet = new();
|
||||
ntf_packet.Message = new();
|
||||
ntf_packet.Message.ClaimUpdateNoti = new();
|
||||
ntf_packet.Message.ClaimUpdateNoti.ClaimId = info.Key;
|
||||
ntf_packet.Message.ClaimUpdateNoti.NormalInfo = info.Value;
|
||||
ntf_packet.Message.ClaimUpdateNoti.MembershipInfo = membership_claim_infos.TryGetValue(info.Key, out var membership_info) ? membership_info : new();
|
||||
if (false == server_logic.onSendPacket(player, ntf_packet))
|
||||
{
|
||||
Log.getLogger().error($"SendPacket Fail");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
193
GameServer/Contents/Claim/Action/ClaimRewardAction.cs
Normal file
193
GameServer/Contents/Claim/Action/ClaimRewardAction.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using GameServer.Reward;
|
||||
using ServerCommon;
|
||||
using ServerControlCenter;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class ClaimRewardReference
|
||||
{
|
||||
public string m_user_guid { get; set; } = string.Empty;
|
||||
public Int32 m_claim_id { get; set; } = 0;
|
||||
public MetaAssets.ClaimType m_claim_type { get; set; } = MetaAssets.ClaimType.Normal;
|
||||
public Int32 m_reward_group_id { get; set; } = 0;
|
||||
public List<MetaAssets.Reward> m_reward_data { get; set; } = new();
|
||||
public ClaimMetaData? m_meta_data { get; set; } = null;
|
||||
|
||||
public ServerCommon.Claim? m_claim { get; set; } = null;
|
||||
|
||||
public List<MetaAssets.Reward> m_rewared_money { get; set; } = new();
|
||||
public List<Item> m_rewarded_items { get; set; } = new();
|
||||
|
||||
public CommonResult m_common_result { get; set; } = new();
|
||||
|
||||
}
|
||||
|
||||
public class ClaimRewardAction : EntityActionBase
|
||||
{
|
||||
public ClaimRewardAction(EntityBase owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> rewardClaim(ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
setActiveIdx(claimRewardRef);
|
||||
IReward reward_proc = new RewardClaim(owner, claimRewardRef.m_user_guid, claimRewardRef);
|
||||
var result = await RewardManager.It.proceedRewardProcess(reward_proc);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
RewardManager.It.postRewardProcess(reward_proc);
|
||||
return new();
|
||||
}
|
||||
|
||||
|
||||
private void setActiveIdx(ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
DateTime now = DateTimeHelper.Current;
|
||||
NullReferenceCheckHelper.throwIfNull(claimRewardRef.m_meta_data, () => $"claimRewardRef.m_meta_data is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(claimRewardRef.m_claim, () => $"claimRewardRef.m_claim is null !!!");
|
||||
|
||||
int lastRewarIdx = claimRewardRef.m_meta_data.DetailInfo.Last().Value.Idx;
|
||||
var claimAttribute = claimRewardRef.m_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(claimAttribute, () => $"claimAttribute is null !!!");
|
||||
|
||||
claimAttribute.ActiveTime = now;
|
||||
int nextActiveIdx = claimAttribute.ActiveRewardIdx + 1;
|
||||
if (nextActiveIdx > lastRewarIdx)
|
||||
{
|
||||
claimAttribute.IsComplete = 1;
|
||||
nextActiveIdx = 0;
|
||||
}
|
||||
claimAttribute.ActiveRewardIdx = nextActiveIdx;
|
||||
claimAttribute.modifiedEntityAttribute();
|
||||
}
|
||||
|
||||
|
||||
public Result claimRewardConditionCheck(ref ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
MetaAssets.ClaimType type = claimRewardRef.m_claim_type;
|
||||
(var result, var claim_meta) = ClaimRewardHelper.getClaimMeta(claimRewardRef.m_claim_id, type);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
claimRewardRef.m_meta_data = claim_meta;
|
||||
|
||||
var claim_action = owner.getEntityAction<ClaimAction>();
|
||||
result = claim_action.getClaim(claimRewardRef.m_claim_id, type, out var claim);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
claimRewardRef.m_claim = claim;
|
||||
|
||||
result = timeConditionCheck(ref claimRewardRef);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
result = rewardConditionCheck(ref claimRewardRef);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Result timeConditionCheck(ref ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(claimRewardRef.m_claim, () => $"claimRewardRef.m_claim is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(claimRewardRef.m_meta_data, () => $"claimRewardRef.m_meta_data is null !!!");
|
||||
|
||||
var attribute = claimRewardRef.m_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(attribute, () => $"attribute is null !!!");
|
||||
|
||||
var active_idx = attribute.ActiveRewardIdx;
|
||||
|
||||
if (false == claimRewardRef.m_meta_data.DetailInfo.TryGetValue(active_idx, out var detailInfo))
|
||||
{
|
||||
var err_msg = $"detailInfo activeIdx = {active_idx} Data not exist";
|
||||
result.setFail(ServerErrorCode.ClaimInfoNotExist, err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
var cool_time = detailInfo.CoolTime;
|
||||
var now_dt = DateTimeHelper.Current;
|
||||
var active_time = attribute.ActiveTime;
|
||||
|
||||
if (now_dt < claimRewardRef.m_meta_data.StartTime || claimRewardRef.m_meta_data.EndTime < now_dt)
|
||||
{
|
||||
var err_msg = $"Claim Not Correct Time activeIdx = {active_idx} metaData.StartTime : {claimRewardRef.m_meta_data.StartTime}, metaData.EndTime : {claimRewardRef.m_meta_data.EndTime} ";
|
||||
result.setFail(ServerErrorCode.ClaimRewardEventEnd, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
|
||||
var apply_cool_second = active_time.AddSeconds(cool_time);
|
||||
|
||||
if (apply_cool_second > now_dt)
|
||||
{
|
||||
var err_msg = $"HandleClaimRewardReq not enough Time to activeIdx = {active_idx} Data not exist";
|
||||
result.setFail(ServerErrorCode.ClaimRewardNotEnoughTime, err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result rewardConditionCheck(ref ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
var result = new Result();
|
||||
NullReferenceCheckHelper.throwIfNull(claimRewardRef.m_claim, () => $"claimRewardRef.m_claim is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(claimRewardRef.m_meta_data, () => $"claimRewardRef.m_meta_data is null !!!");
|
||||
|
||||
var attribute = claimRewardRef.m_claim.getEntityAttribute<ClaimAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(attribute, () => $"attribute is null !!!");
|
||||
|
||||
var active_idx = attribute.ActiveRewardIdx;
|
||||
|
||||
if (false == claimRewardRef.m_meta_data.DetailInfo.TryGetValue(active_idx, out var detailInfo))
|
||||
{
|
||||
var err_msg = $"detailInfo activeIdx = {active_idx} Data not exist";
|
||||
result.setFail(ServerErrorCode.ClaimInfoNotExist, err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
int rewardGroupId = detailInfo.RewardGroupId;
|
||||
if (!MetaData.Instance._RewardMetaTable.TryGetValue(rewardGroupId, out var rewardList))
|
||||
{
|
||||
var err_msg = $"_RewardDataTable not exist info rewardGroupId = {rewardGroupId}";
|
||||
result.setFail(ServerErrorCode.RewardInfoNotExist, err_msg);
|
||||
return result;
|
||||
}
|
||||
claimRewardRef.m_reward_group_id = rewardGroupId;
|
||||
claimRewardRef.m_reward_data.Clear();
|
||||
foreach (var reward in rewardList)
|
||||
{
|
||||
claimRewardRef.m_reward_data.Add(reward.Reward);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
24
GameServer/Contents/Claim/ClaimCheat.cs
Normal file
24
GameServer/Contents/Claim/ClaimCheat.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
[ChatCommandAttribute("resetclaim", typeof(ChatCommandResetClaim), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class ChatCommandResetClaim : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
var claim_action = player.getEntityAction<ClaimAction>();
|
||||
|
||||
await claim_action.cheatClaimReset();
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("claimupdaterewardable", typeof(ChatCommandRewardClaim), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class ChatCommandRewardClaim : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
var claim_action = player.getEntityAction<ClaimAction>();
|
||||
await claim_action.cheatClaimUpdateRewardable();
|
||||
}
|
||||
}
|
||||
107
GameServer/Contents/Claim/DBQuery/DBQClaimReadAll.cs
Normal file
107
GameServer/Contents/Claim/DBQuery/DBQClaimReadAll.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class DBQClaimReadAll : QueryExecutorBase
|
||||
{
|
||||
private MetaAssets.ClaimType m_claim_type { get; set; } = MetaAssets.ClaimType.None;
|
||||
private string m_pk { get; set; } = string.Empty;
|
||||
private string m_sk { get; set; } = string.Empty;
|
||||
|
||||
private readonly string m_combination_key_for_pk;
|
||||
|
||||
public DBQClaimReadAll(string combinationKeyForPk)
|
||||
: base(typeof(DBQClaimReadAll).Name)
|
||||
{
|
||||
m_combination_key_for_pk = combinationKeyForPk;
|
||||
}
|
||||
|
||||
|
||||
//===================================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//===================================================================================================
|
||||
public override Task<Result> onPrepareQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var doc = new ClaimDoc(owner.getUserGuid());
|
||||
doc.setCombinationKeyForPK(m_combination_key_for_pk);
|
||||
|
||||
var error_code = doc.onApplyPKSK();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(error_code, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
m_pk = doc.getPK();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
//===================================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//===================================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var query_batch = getQueryBatch();
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => "query_batch is null !!!");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
var query_config = db_connector.makeQueryConfigForReadByPKOnly(m_pk);
|
||||
|
||||
(result, var read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<ClaimDoc>(query_config, eventTid: query_batch.getTransId());
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var claim_action = owner.getEntityAction<ClaimAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_action, () => "claim_action is null !!!");
|
||||
|
||||
foreach (var read_doc in read_docs)
|
||||
{
|
||||
var set_result = claim_action.setClaimFromDoc(read_doc);
|
||||
if (set_result.isFail())
|
||||
{
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
claim_action.setDataLoad(true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//===================================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//===================================================================================================
|
||||
public override Task onQueryResponseCommit()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
//===================================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//===================================================================================================
|
||||
public override Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private new Player? getOwner() => getQueryBatch()?.getLogActor() as Player;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
36
GameServer/Contents/Claim/Log/CheatClaimResetBusinessLog.cs
Normal file
36
GameServer/Contents/Claim/Log/CheatClaimResetBusinessLog.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CheatClaimResetBusinessLog : ILogInvokerEx
|
||||
{
|
||||
CheatClaimResetLogInfo m_info;
|
||||
|
||||
public CheatClaimResetBusinessLog(MetaAssets.ClaimType claimType, Int32 claimId, Int32 ActiveRewardIdx)
|
||||
: base(LogDomainType.ClaimReward)
|
||||
{
|
||||
m_info = CheatClaimResetLogInfo.creatCheatClaimResetLogInfo(this, claimType, claimId, ActiveRewardIdx);
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(m_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CheatClaimRewardableBusinessLog : ILogInvokerEx
|
||||
{
|
||||
CheatClaimRewardableLogInfo m_info;
|
||||
|
||||
public CheatClaimRewardableBusinessLog(MetaAssets.ClaimType claimType, Int32 claimId, Int32 ActiveRewardIdx)
|
||||
: base(LogDomainType.ClaimReward)
|
||||
{
|
||||
m_info = CheatClaimRewardableLogInfo.creatCheatClaimRewardableLogInfo(this, claimType, claimId, ActiveRewardIdx);
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(m_info);
|
||||
}
|
||||
}
|
||||
35
GameServer/Contents/Claim/Log/ClaimRewardBusinessLog.cs
Normal file
35
GameServer/Contents/Claim/Log/ClaimRewardBusinessLog.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class ClaimRewardBusinessLog : ILogInvokerEx
|
||||
{
|
||||
ClaimRewardLogInfo m_info;
|
||||
|
||||
public ClaimRewardBusinessLog(int claimId, int claimType, int rewardDataId)
|
||||
: base(LogDomainType.ClaimReward)
|
||||
{
|
||||
m_info = new ClaimRewardLogInfo(this, claimId, claimType, rewardDataId);
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(m_info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.ClaimRewardReq), typeof(ClaimRewardPacketHandler), typeof(GameLoginListener))]
|
||||
public class ClaimRewardPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public override async Task<Result> onProcessPacket(ISession session, IMessage recvMessage)
|
||||
{
|
||||
var owner = session as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!!");
|
||||
|
||||
var request = recv_msg.Request.ClaimRewardReq;
|
||||
var claim_type = request.ClaimType;
|
||||
var claim_id = request.ClaimId;
|
||||
|
||||
|
||||
ClaimRewardReference claim_reward_ref = new();
|
||||
claim_reward_ref.m_claim_id = claim_id;
|
||||
|
||||
|
||||
System.Enum.TryParse(claim_type.ToString(), out MetaAssets.ClaimType parsedType);
|
||||
claim_reward_ref.m_claim_type = parsedType;
|
||||
|
||||
claim_reward_ref.m_user_guid = owner.getUserGuid();
|
||||
|
||||
var result = await claimReward(owner, claim_reward_ref);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_GS2C_ACK_CLAIM_REWARD_FAIL(owner, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
send_GS2C_ACK_CLAIM_REWARD(owner, result, claim_reward_ref);
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(claim_reward_ref.m_meta_data, () => $"claim_reward_ref.m_meta_data is null !!!");
|
||||
var rewards = claim_reward_ref.m_meta_data.DetailInfo.Values.ToList();
|
||||
foreach (var reward in rewards)
|
||||
{
|
||||
await QuestManager.It.QuestCheck(owner, new QuestReward(EQuestEventTargetType.REWARD, EQuestEventNameType.RECEIVED, reward.RewardGroupId));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<Result> claimReward(Player owner, ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
var claim_reward_action = owner.getEntityAction<ClaimRewardAction>();
|
||||
|
||||
var result = claim_reward_action.claimRewardConditionCheck(ref claimRewardRef);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
result = await owner.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "RewardClaim", delegateRewardClaim);
|
||||
if (result.isFail())
|
||||
{
|
||||
string err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
async Task<Result> delegateRewardClaim() => await rewardClaim(owner, claimRewardRef);
|
||||
}
|
||||
|
||||
private async Task<Result> rewardClaim(Player owner, ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
var claim_reward_action = owner.getEntityAction<ClaimRewardAction>();
|
||||
var result = await claim_reward_action.rewardClaim(claimRewardRef);
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(owner, LogActionType.ClaimReward, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
var log_invoker = new ClaimRewardBusinessLog(claimRewardRef.m_claim_id, (int)claimRewardRef.m_claim_type, claimRewardRef.m_reward_group_id);
|
||||
batch.appendBusinessLog(log_invoker);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var found_transaction_runner = owner.findTransactionRunner(TransactionIdType.PrivateContents);
|
||||
NullReferenceCheckHelper.throwIfNull(found_transaction_runner, () => $"found_transaction_runner is null !!! - {owner.toBasicString()}");
|
||||
var common_result = found_transaction_runner.getCommonResult();
|
||||
claimRewardRef.m_common_result = common_result;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool send_GS2C_ACK_CLAIM_REWARD_FAIL(Player owner, Result result)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.ClaimRewardRes = new();
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(owner, ack_packet)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool send_GS2C_ACK_CLAIM_REWARD(Player owner, Result result, ClaimRewardReference claimRewardRef)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.ClaimRewardRes = new();
|
||||
ack_packet.Response.ClaimRewardRes.ClaimId = claimRewardRef.m_claim_id;
|
||||
ack_packet.Response.ClaimRewardRes.CommonResult = claimRewardRef.m_common_result;
|
||||
//var rewarded_items = claimRewardRef.m_rewarded_items;
|
||||
//var rewarded_money = claimRewardRef.m_rewared_money;
|
||||
//var items = RewardManager.Instance.convertItemAndMoneyToItem(rewarded_items, rewarded_money);
|
||||
//ack_packet.Response.ClaimRewardRes.RewardItems.AddRange(items);
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(owner, ack_packet)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.GetClaimInfoReq), typeof(GetClaimInfoPacketHandler), typeof(GameLoginListener))]
|
||||
public class GetClaimInfoPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public override async Task<Result> onProcessPacket(ISession session, IMessage recvMessage)
|
||||
{
|
||||
var owner = session as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "player is null !!!");
|
||||
|
||||
var claim_action = owner.getEntityAction<ClaimAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(claim_action, () => $"claim action is null !!! - {owner.toBasicString()}");
|
||||
//var result = await claim_action.loadClaim();
|
||||
// if (result.isFail())
|
||||
// {
|
||||
// send_GS2C_ACK_GET_CLAIM_ERROR(owner, result);
|
||||
// }
|
||||
|
||||
send_GS2C_ACK_GET_CLAIM_SUCCESS(owner);
|
||||
return await Task.FromResult(new Result());
|
||||
}
|
||||
|
||||
|
||||
private static bool send_GS2C_ACK_GET_CLAIM_SUCCESS(Player owner)
|
||||
{
|
||||
var normal_claim_infos = ClaimRewardHelper.MakeClaimSendInfo(owner, MetaAssets.ClaimType.Normal);
|
||||
var membership_claim_infos = ClaimRewardHelper.MakeClaimSendInfo(owner, MetaAssets.ClaimType.Membership);
|
||||
|
||||
foreach (var normal_info in normal_claim_infos)
|
||||
{
|
||||
var claim_id = normal_info.Key;
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
ack_packet.Response.GetClaimInfoRes = new();
|
||||
ack_packet.Response.GetClaimInfoRes.ClaimId = claim_id;
|
||||
ack_packet.Response.GetClaimInfoRes.NormalInfo = normal_info.Value;
|
||||
ack_packet.Response.GetClaimInfoRes.MembershipInfo = new();
|
||||
if (true == membership_claim_infos.TryGetValue(claim_id, out var membership_info))
|
||||
{
|
||||
ack_packet.Response.GetClaimInfoRes.MembershipInfo = membership_info;
|
||||
}
|
||||
GameServerApp.getServerLogic().onSendPacket(owner, ack_packet);
|
||||
}
|
||||
|
||||
if (normal_claim_infos.Count == 0)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
ack_packet.Response.GetClaimInfoRes = new();
|
||||
ack_packet.Response.GetClaimInfoRes.ClaimId = 0;
|
||||
ack_packet.Response.GetClaimInfoRes.NormalInfo = new();
|
||||
ack_packet.Response.GetClaimInfoRes.MembershipInfo = new();
|
||||
GameServerApp.getServerLogic().onSendPacket(owner, ack_packet);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static bool send_GS2C_ACK_GET_CLAIM_ERROR(Player owner, Result result)
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.GetClaimInfoRes = new();
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(owner, ack_packet)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
921
GameServer/Contents/Craft/Action/CraftAction.cs
Normal file
921
GameServer/Contents/Craft/Action/CraftAction.cs
Normal file
@@ -0,0 +1,921 @@
|
||||
using MetaAssets;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System.Collections.Concurrent;
|
||||
using NeoSmart.AsyncLock;
|
||||
using GameServer.PacketHandler;
|
||||
using UGCNPC_GUID = System.String;
|
||||
using META_ID = System.UInt32;
|
||||
using ANCHOR_GUID = System.String;
|
||||
using LOCATION_UNIQUE_ID = System.String;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class CraftAction : EntityActionBase
|
||||
{
|
||||
private ConcurrentDictionary<ANCHOR_GUID, Craft> m_Crafts = new();
|
||||
private bool m_isUpdateCraft = false;
|
||||
|
||||
public CraftAction(Player owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
m_Crafts.Clear();
|
||||
}
|
||||
|
||||
public bool isCraftingHome()
|
||||
{
|
||||
if(m_Crafts.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setUpdateCraft(bool isUpdateCraft)
|
||||
{
|
||||
m_isUpdateCraft = isUpdateCraft;
|
||||
}
|
||||
|
||||
public bool isAnchorCrafting(string anchorGuid)
|
||||
{
|
||||
return m_Crafts.ContainsKey(anchorGuid);
|
||||
}
|
||||
|
||||
public List<CraftInfo> getCraftInfoList()
|
||||
{
|
||||
return m_Crafts.Values.Select(x => x.toCraftData4Client()).ToList();
|
||||
}
|
||||
|
||||
public bool getCraftInfo(string anchorGuid, [MaybeNullWhen(false)] out CraftInfo craftInfo )
|
||||
{
|
||||
craftInfo = default;
|
||||
|
||||
if (!m_Crafts.TryGetValue(anchorGuid, out var craft))
|
||||
return false;
|
||||
|
||||
craftInfo = craft.toCraftData4Client();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<Result> AddCraftFromDocs(List<CraftDoc> craftDocs)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
m_Crafts.Clear();
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
|
||||
foreach (var craft_doc in craftDocs)
|
||||
{
|
||||
(result, var craft) = await Craft.createCraftFromDoc(player, craft_doc);
|
||||
if(craft is null)
|
||||
{
|
||||
err_msg = $"Failed to create craft from doc";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
var craft_attribute = craft.getEntityAttribute<CraftAttribute>();
|
||||
if (craft_attribute is null)
|
||||
{
|
||||
err_msg = $"craft_attribute is null";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
if (m_Crafts.TryAdd(craft_attribute.AnchorGuid, craft) == false)
|
||||
{
|
||||
err_msg = $"Failed to get craft attribute : {nameof(CraftAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> ReloadCraft()
|
||||
{
|
||||
var result = new Result();
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var craft_doc = new CraftDoc();
|
||||
craft_doc.setCombinationKeyForPK(player.getUserGuid());
|
||||
craft_doc.onApplyPKSK();
|
||||
var query_config = server_logic.getDynamoDbClient().makeQueryConfigForReadByPKOnly(craft_doc.getPK());
|
||||
(result, var craft_docs) = await server_logic.getDynamoDbClient().simpleQueryDocTypesWithQueryOperationConfig<CraftDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await AddCraftFromDocs(craft_docs);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> StartCraftProcess(ANCHOR_GUID anchor_guid, META_ID craft_meta_id, UGCNPC_GUID beacon_guid, Pos beacon_pos, int craft_count)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if(m_isUpdateCraft == true)
|
||||
{
|
||||
await ReloadCraft();
|
||||
}
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
if (MetaData.Instance._CraftingMetaTable.TryGetValue((int)craft_meta_id, out var crafting_meta_data) == false)
|
||||
{
|
||||
err_msg = $"Not found meta of crafting !!! : craft_meta_id : {craft_meta_id} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = checkStartCrafting(anchor_guid, crafting_meta_data, beacon_guid, craft_count);
|
||||
if (result.isFail())
|
||||
{
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!!");
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!!");
|
||||
|
||||
var myhome_agent_action = player.getEntityAction<MyhomeAgentAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(myhome_agent_action, () => $"myhome_agent_action is null !!!");
|
||||
|
||||
DateTime now = DateTimeHelper.Current;
|
||||
DateTime craft_finish_date = now.AddSeconds(crafting_meta_data.CraftingTime * craft_count);
|
||||
|
||||
string myhome_guid = string.Empty;
|
||||
|
||||
UgcNpc? ugc_npc = null;
|
||||
if (beacon_guid != string.Empty)
|
||||
{
|
||||
ugc_npc = player_action.findUgcNpc(beacon_guid);
|
||||
if (ugc_npc == null)
|
||||
{
|
||||
err_msg = $"UgcNpc Not Found UgcNpc Guid : {beacon_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
craft_finish_date = craft_finish_date.AddSeconds(-1 * crafting_meta_data.Beacon_ReduceTime * craft_count);
|
||||
myhome_guid = myhome_agent_action.getMyHomeGuidByAnchorGuid(anchor_guid);
|
||||
if(myhome_guid.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Failed to get Myhome Guid. anchor_guid : {anchor_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.AnchorIsNotInMyhome, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
var fn_start_craft_profile = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
|
||||
DynamoDbDocBase? dynamoDbDocBase = null;
|
||||
|
||||
if (ugc_npc != null)
|
||||
{
|
||||
EntityPos entityPos = beacon_pos == null ? new EntityPos() : new EntityPos() { X = beacon_pos.X, Y = beacon_pos.Y, Z = beacon_pos.Z, FacingAngle = beacon_pos.Angle };
|
||||
modifyNpcData(player, ugc_npc, anchor_guid, entityPos);
|
||||
dynamoDbDocBase = MakeNewNpcLocationDoc(ugc_npc, entityPos, anchor_guid, myhome_guid);
|
||||
}
|
||||
|
||||
List<Item> decrease_changed_items = new List<Item>();
|
||||
foreach (var material in crafting_meta_data.Material)
|
||||
{
|
||||
(result, var found_delete_item) = await inventory_action.tryDeleteItemByMetaId((META_ID)material.ItemId, (ushort)(material.ItemValue * craft_count));
|
||||
if (result.isFail())
|
||||
{
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
decrease_changed_items.AddRange(found_delete_item);
|
||||
}
|
||||
|
||||
(result, var craft) = await Craft.createCraft(player, anchor_guid, craft_meta_id, beacon_guid, now, craft_finish_date, craft_count);
|
||||
if (result.isFail())
|
||||
{
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(craft, () => $"craft is null !!!");
|
||||
|
||||
var craft_attribute = craft.getEntityAttribute<CraftAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_attribute, () => $"craft_attribute is null !!!");
|
||||
|
||||
var task_log_data = CraftBusinessLogHelper.toCraftLogInfo(craft_attribute);
|
||||
invokers.Add(new CraftBusinessLog(task_log_data));
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.CraftStart
|
||||
, server_logic.getDynamoDbClient() );
|
||||
{
|
||||
if(dynamoDbDocBase != null) batch.addQuery(new DBQEntityWrite(new List<DynamoDbDocBase>() { dynamoDbDocBase }));
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
m_Crafts.TryAdd(anchor_guid, craft);
|
||||
|
||||
if (ugc_npc != null)
|
||||
{
|
||||
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
|
||||
ugc_npc_action.setCountingAsConnectedUser(false);
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
|
||||
var map = game_zone_action.getLinkedToMap();
|
||||
NullReferenceCheckHelper.throwIfNull(map, () => $"map is null !!!");
|
||||
|
||||
result = await ugc_npc_action.tryLocateInGameZone(map, myhome_guid);
|
||||
if(result.isSuccess())
|
||||
{
|
||||
UgcNpcNotifyHelper.send_GS2C_NTF_BEACON_COMPACT_UPDATE(player, ugc_npc, ugc_npc_action.toUgcNpcCompact());
|
||||
}
|
||||
}
|
||||
|
||||
StartCraftPacketHandler.send_S2C_ACK_START_CRAFT(player, result, craft, decrease_changed_items, beacon_pos);
|
||||
game_zone_action.broadcast(player, CraftNotifyHelper.makeNotiCraftInfoPacket(m_Crafts.Select(x => x.Value.toCraftData4Client()).ToList(), player.getUserGuid()));
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "StartCraft", fn_start_craft_profile);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void modifyNpcData(Player player, UgcNpc ugc_npc, string anchor_guid, EntityPos currPos)
|
||||
{
|
||||
var anchor_meta_id = getAnchorMetaId(player, anchor_guid);
|
||||
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
ugc_npc_action.modifyStateInfo( EntityStateType.UsingByCrafting
|
||||
, currPos
|
||||
, anchor_guid, (META_ID)anchor_meta_id );
|
||||
}
|
||||
|
||||
private int getAnchorMetaId(Player player, string anchor_guid)
|
||||
{
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
var crafting_anchor = game_zone_action.GetAnchor(anchor_guid);
|
||||
if (crafting_anchor == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return crafting_anchor.AnchorProp.TableId;
|
||||
}
|
||||
|
||||
private Result checkStartCrafting(ANCHOR_GUID anchor_guid, CraftingMetaData crafting_meta_data, UGCNPC_GUID beacon_guid, int craft_count)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (m_Crafts.TryGetValue(anchor_guid, out var craft) == true)
|
||||
{
|
||||
err_msg = $"this Anchor is already Crafting now. anchor_guid : {anchor_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingAlreadyCrafting, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (beacon_guid != string.Empty)
|
||||
{
|
||||
result = checkNpcState(beacon_guid);
|
||||
if (result.isFail()) { return result; }
|
||||
}
|
||||
|
||||
result = checkAbility(crafting_meta_data,beacon_guid);
|
||||
if (result.isFail()) { return result; }
|
||||
|
||||
result = checkAnchor(crafting_meta_data, anchor_guid);
|
||||
if(result.isFail()) { return result; }
|
||||
|
||||
//레시피 확인
|
||||
if (crafting_meta_data.RecipeType == ERecipeType.Add)
|
||||
{
|
||||
result = checkRecipe((META_ID)crafting_meta_data.Id);
|
||||
if (result.isFail()) { return result; }
|
||||
}
|
||||
|
||||
if(crafting_meta_data.max_craft_limit < craft_count || craft_count < 1)
|
||||
{
|
||||
err_msg = $"craft limit is over. craft meta ID : {crafting_meta_data.Id} - max_craft_limit : {crafting_meta_data.max_craft_limit} - request craft_count : {craft_count} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftInvalidRequestCount, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result checkRecipe(META_ID craft_meta_id)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var craft_recipe_action = player.getEntityAction<CraftRecipeAction>();
|
||||
if (craft_recipe_action.HasRecipe((META_ID)craft_meta_id) == false)
|
||||
{
|
||||
err_msg = $"Recipe is not register. Craft_meta_id : {craft_meta_id} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingRecipeIsNotRegister, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result checkNpcState(UGCNPC_GUID ugcNpc_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
var ugc_npc = player_action.findUgcNpc(ugcNpc_guid);
|
||||
if (ugc_npc == null)
|
||||
{
|
||||
err_msg = $"UgcNpc Not Found UgcNpc Guid : {ugcNpc_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
var ugc_ncp_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_ncp_attribute, () => $"ugc_ncp_attribute is null !!!");
|
||||
if (ugc_ncp_attribute.State != EntityStateType.None)
|
||||
{
|
||||
result.setFail(ServerErrorCode.NpcIsBusy, err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result checkAbility(CraftingMetaData crafting_meta_data, UGCNPC_GUID ugcNpc_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var ability_action = player.getEntityAction<AbilityAction>();
|
||||
if (ugcNpc_guid != string.Empty)
|
||||
{
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
var ugc_npc = player_action.findUgcNpc(ugcNpc_guid);
|
||||
if (ugc_npc == null)
|
||||
{
|
||||
err_msg = $"UgcNpc Not Found UgcNpc Guid : {ugcNpc_guid} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
ability_action = ugc_npc.getEntityAction<AbilityAction>();
|
||||
}
|
||||
|
||||
foreach (var attribute in crafting_meta_data.Attribute)
|
||||
{
|
||||
if (false == EnumHelper.tryParse<AttributeType>(attribute.AttributeName, out var attribute_type))
|
||||
{
|
||||
err_msg = $"Invalid Ability Enum Type : {attribute_type} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ServerTypeInvalid, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
var attribute_value = ability_action.getAbility(attribute_type);
|
||||
if (attribute_value == null)
|
||||
{
|
||||
err_msg = $"Invalid Ability Enum Type : {attribute_type} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ServerTypeInvalid, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (attribute_value < attribute.AttributeValue)
|
||||
{
|
||||
err_msg = $"Not Enough Attribute for Craft. attribute name : {attribute_type}, need attribute : {attribute_value}, current attribute : {attribute.AttributeValue} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.NotEnoughAttribute, err_msg);
|
||||
Log.getLogger().info(err_msg);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result checkAnchor(CraftingMetaData crafting_meta_data, ANCHOR_GUID anchor_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
var crafting_anchor = game_zone_action.GetAnchor(anchor_guid);
|
||||
if (crafting_anchor == null)
|
||||
{
|
||||
err_msg = $"anchor is not placed !!! - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingAnchorIsNotPlaced, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (MetaData.Instance._ItemTable.TryGetValue(crafting_anchor.AnchorProp.TableId, out var item_meta_data) == false)
|
||||
{
|
||||
err_msg = $"Not found meta of Item !!! : item_meta_id : {crafting_anchor.AnchorProp.TableId} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (item_meta_data.PropSmallType != crafting_meta_data.PropSmallType)
|
||||
{
|
||||
err_msg = $"Group ID Not match with recipe. item PropSmallType : {item_meta_data.PropSmallType}, crafting PropSmallType : {crafting_meta_data.PropSmallType} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingAnchorIsNotMatchWithRecipe, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private NpcLocationInTargetDoc MakeNewNpcLocationDoc(UgcNpc ugcNpc, EntityPos currPos, string anchorMetaGuid, string myhomeMetaGuid)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(ugcNpc, () => $"ugcNpc is null !!! - {player.toBasicString()}");
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var curr_map = game_zone_action.getLinkedToMap();
|
||||
NullReferenceCheckHelper.throwIfNull(curr_map, () => $"curr_map is null !!! - {player.toBasicString()}");
|
||||
|
||||
var ugc_npc_action = ugcNpc.getEntityAction<UgcNpcAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var ugc_npc_attribute = ugcNpc.getEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var location_unique_id = curr_map.makeLOCATION_UNIQUE_IDByMetaId(myhomeMetaGuid);
|
||||
|
||||
var npcLocation = new NpcLocation() { AnchorMetaGuid = anchorMetaGuid, CurrentPos = currPos };
|
||||
|
||||
var doc = new NpcLocationInTargetDoc(location_unique_id, anchorMetaGuid
|
||||
, EntityType.UgcNpc, ugc_npc_attribute.UgcNpcMetaGuid, npcLocation
|
||||
, ugc_npc_attribute.OwnerEntityType, ugc_npc_attribute.OwnerGuid);
|
||||
|
||||
doc.setQueryType(QueryType.Insert);
|
||||
return doc;
|
||||
}
|
||||
|
||||
private NpcLocationInTargetDoc MakeDeleteNpcLocationDoc(string anchorMetaGuid, string myhomeMetaGuid)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var curr_map = game_zone_action.getLinkedToMap();
|
||||
NullReferenceCheckHelper.throwIfNull(curr_map, () => $"curr_map is null !!! - {player.toBasicString()}");
|
||||
|
||||
|
||||
var location_unique_id = curr_map.makeLOCATION_UNIQUE_IDByMetaId(myhomeMetaGuid);
|
||||
|
||||
return new NpcLocationInTargetDoc(location_unique_id, anchorMetaGuid);
|
||||
}
|
||||
public async Task<Result> StopCraftProcess(ANCHOR_GUID anchor_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (m_isUpdateCraft == true)
|
||||
{
|
||||
await ReloadCraft();
|
||||
}
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
if (m_Crafts.TryGetValue(anchor_guid, out var craft) == false)
|
||||
{
|
||||
err_msg = $"this Anchor is not Crafting now. anchor_guid : {anchor_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingNotCraftingAnchor, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
StopCraftPacketHandler.send_S2C_ACK_STOP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Int32 craft_meta_id = 0;
|
||||
|
||||
var fn_stop_craft_profile = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
|
||||
DynamoDbDocBase? dynamoDbDocBase = null;
|
||||
|
||||
var craft_attribute = craft.getEntityAttribute<CraftAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_attribute, () => $"craft_attribute is null !!!");
|
||||
craft_attribute.deleteEntityAttribute();
|
||||
|
||||
UgcNpc? ugc_npc = null;
|
||||
if (craft_attribute.BeaconGuid != string.Empty)
|
||||
{
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
ugc_npc = player_action.findUgcNpc(craft_attribute.BeaconGuid);
|
||||
if (ugc_npc == null)
|
||||
{
|
||||
err_msg = $"UgcNpc Not Found UgcNpc Guid : {craft_attribute.BeaconGuid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
StopCraftPacketHandler.send_S2C_ACK_STOP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null - {player.toBasicString()}");
|
||||
|
||||
var myhome_agent_action = player.getEntityAction<MyhomeAgentAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(myhome_agent_action, () => $"myhome_agent_action is null !!!");
|
||||
|
||||
var myhome_guid = myhome_agent_action.getMyHomeGuidByAnchorGuid(anchor_guid);
|
||||
if (myhome_guid.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Failed to get Myhome Guid. anchor_guid : {anchor_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.AnchorIsNotInMyhome, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
StopCraftPacketHandler.send_S2C_ACK_STOP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
ugc_npc_action.modifyStateInfo(EntityStateType.None, new EntityPos(), "");
|
||||
dynamoDbDocBase = MakeDeleteNpcLocationDoc(anchor_guid, myhome_guid);
|
||||
}
|
||||
|
||||
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!!");
|
||||
|
||||
if (MetaData.Instance._CraftingMetaTable.TryGetValue((int)craft_attribute.CraftMetaId, out var crafting_meta_data) == false)
|
||||
{
|
||||
err_msg = $"Not found meta of Item !!! : CraftingMetaId:{craft_attribute.CraftMetaId} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
StopCraftPacketHandler.send_S2C_ACK_STOP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<Item> Increase_changed_items = new List<Item>();
|
||||
foreach(var material in crafting_meta_data.Material)
|
||||
{
|
||||
(result, var crafting_items) = await inventory_action.tryTakalbleToBag((META_ID)material.ItemId, (ushort)(material.ItemValue * craft_attribute.CraftCount));
|
||||
if (result.isFail())
|
||||
{
|
||||
StopCraftPacketHandler.send_S2C_ACK_STOP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Increase_changed_items.AddRange(crafting_items);
|
||||
}
|
||||
|
||||
var task_log_data = CraftBusinessLogHelper.toCraftLogInfo(craft_attribute);
|
||||
invokers.Add(new CraftBusinessLog(task_log_data));
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.CraftStop
|
||||
, server_logic.getDynamoDbClient() );
|
||||
{
|
||||
if(dynamoDbDocBase != null) batch.addQuery(new DBQEntityDelete(dynamoDbDocBase));
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
StopCraftPacketHandler.send_S2C_ACK_STOP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
m_Crafts.TryRemove(anchor_guid, out craft);
|
||||
|
||||
if (ugc_npc != null)
|
||||
{
|
||||
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
result = await ugc_npc_action.tryRemoveInGameZone();
|
||||
if(result.isSuccess())
|
||||
{
|
||||
UgcNpcNotifyHelper.send_GS2C_NTF_BEACON_COMPACT_UPDATE(player, ugc_npc, ugc_npc_action.toUgcNpcCompact());
|
||||
}
|
||||
}
|
||||
|
||||
StopCraftPacketHandler.send_S2C_ACK_STOP_CRAFT(player, result, anchor_guid, craft_attribute.BeaconGuid, Increase_changed_items);
|
||||
game_zone_action.broadcast(player, CraftNotifyHelper.makeNotiCraftInfoPacket(m_Crafts.Select(x => x.Value.toCraftData4Client()).ToList(), player.getUserGuid()));
|
||||
|
||||
craft_meta_id = (Int32)craft_attribute.CraftMetaId;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "StopCraft", fn_stop_craft_profile);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransaction() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
if (craft_meta_id > 0)
|
||||
{
|
||||
await QuestManager.It.QuestCheck(player, new QuestCrafting(EQuestEventTargetType.CRAFTING, EQuestEventNameType.STOPPED, craft_meta_id));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> FinishCraftProcess(ANCHOR_GUID anchor_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (m_isUpdateCraft == true)
|
||||
{
|
||||
await ReloadCraft();
|
||||
}
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
|
||||
if (m_Crafts.TryGetValue(anchor_guid, out var craft) == false)
|
||||
{
|
||||
err_msg = $"this Anchor is not Crafting now. anchor_guid : {anchor_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingNotCraftingAnchor, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
var craft_attribute = craft.getOriginEntityAttribute<CraftAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_attribute, () => $"craft_attribute is null !!!");
|
||||
|
||||
DateTime now = DateTimeHelper.Current;
|
||||
if (craft_attribute.CraftFinishTime > now)
|
||||
{
|
||||
err_msg = $"Crafting Not Finish Time : now : {now} - craftFinishTime : {craft_attribute.CraftFinishTime} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingNotFinish, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (MetaData.Instance._CraftingMetaTable.TryGetValue((int)craft_attribute.CraftMetaId, out var crafting_meta_data) == false)
|
||||
{
|
||||
err_msg = $"Not found meta of Item !!! : CraftingMetaId:{craft_attribute.CraftMetaId} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
var fn_finish_craft_profile = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
DynamoDbDocBase? dynamoDbDocBase = null;
|
||||
|
||||
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!!");
|
||||
|
||||
var craft_attribute = craft.getEntityAttribute<CraftAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_attribute, () => $"craft_attribute is null !!!");
|
||||
craft_attribute.deleteEntityAttribute();
|
||||
|
||||
List<Item> Increase_changed_items = new List<Item>();
|
||||
(result, var crafting_items) = await inventory_action.tryTakalbleToBag((META_ID)crafting_meta_data.Crafting_ItemId, (ushort)(crafting_meta_data.Crafting_ItemValue * craft_attribute.CraftCount));
|
||||
if (result.isFail())
|
||||
{
|
||||
FinishCraftPacketHandler.send_S2C_ACK_FINISH_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Increase_changed_items.AddRange(crafting_items);
|
||||
|
||||
UgcNpc? ugc_npc = null;
|
||||
if (craft_attribute.BeaconGuid != string.Empty)
|
||||
{
|
||||
var player_action = player.getEntityAction<PlayerAction>();
|
||||
ugc_npc = player_action.findUgcNpc(craft_attribute.BeaconGuid);
|
||||
if (ugc_npc == null)
|
||||
{
|
||||
err_msg = $"UgcNpc Not Found UgcNpc Guid : {craft_attribute.BeaconGuid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
FinishCraftPacketHandler.send_S2C_ACK_FINISH_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var myhome_agent_action = player.getEntityAction<MyhomeAgentAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(myhome_agent_action, () => $"myhome_agent_action is null !!!");
|
||||
|
||||
var myhome_guid = myhome_agent_action.getMyHomeGuidByAnchorGuid(anchor_guid);
|
||||
if (myhome_guid.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Failed to get Myhome Guid. anchor_guid : {anchor_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.AnchorIsNotInMyhome, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
FinishCraftPacketHandler.send_S2C_ACK_FINISH_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null - {player.toBasicString()}");
|
||||
|
||||
ugc_npc_action.modifyStateInfo(EntityStateType.None, new EntityPos(), "");
|
||||
dynamoDbDocBase = MakeDeleteNpcLocationDoc(anchor_guid, myhome_guid);
|
||||
|
||||
(result, var bonus_items) = await inventory_action.tryTakalbleToBag((META_ID)crafting_meta_data.Beacon_BonusItemId, (ushort)(1 * craft_attribute.CraftCount));
|
||||
if (result.isFail())
|
||||
{
|
||||
FinishCraftPacketHandler.send_S2C_ACK_FINISH_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Increase_changed_items.AddRange(bonus_items);
|
||||
}
|
||||
|
||||
var task_log_data = CraftBusinessLogHelper.toCraftLogInfo(craft_attribute);
|
||||
invokers.Add(new CraftBusinessLog(task_log_data));
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CraftFinish
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
if (dynamoDbDocBase != null) batch.addQuery(new DBQEntityDelete(dynamoDbDocBase));
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
FinishCraftPacketHandler.send_S2C_ACK_FINISH_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
m_Crafts.TryRemove(anchor_guid, out craft);
|
||||
|
||||
if (ugc_npc != null)
|
||||
{
|
||||
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
result = await ugc_npc_action.tryRemoveInGameZone();
|
||||
if (result.isFail())
|
||||
{
|
||||
string room_id = string.Empty;
|
||||
LOCATION_UNIQUE_ID unique_id = string.Empty;
|
||||
int map_id = 0;
|
||||
var map = game_zone_action.getLinkedToMap();
|
||||
if (map is not null)
|
||||
{
|
||||
room_id = map.m_room_id;
|
||||
unique_id = map.getLocationUniqueId();
|
||||
map_id = map.MapMId;
|
||||
}
|
||||
err_msg = $"Failed to tryRemoveInGameZone Player room_id : {room_id}, Player Map Location id : {unique_id}, Player MapMid : {map_id}, BeaconGuid : {craft_attribute.BeaconGuid} - {getOwner().toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
FinishCraftPacketHandler.send_S2C_ACK_FINISH_CRAFT(player, result, anchor_guid, craft_attribute.BeaconGuid, Increase_changed_items);
|
||||
game_zone_action.broadcast(player, CraftNotifyHelper.makeNotiCraftInfoPacket(m_Crafts.Select(x => x.Value.toCraftData4Client()).ToList(), player.getUserGuid()));
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "FinishCraft", fn_finish_craft_profile);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransaction() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
if (crafting_meta_data.Crafting_ItemId > 0)
|
||||
{
|
||||
await QuestManager.It.QuestCheck(player, new QuestCrafting(EQuestEventTargetType.CRAFTING, EQuestEventNameType.COMPLETED, crafting_meta_data.Crafting_ItemId));
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result cheatAllCraftFinish()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var craftList = m_Crafts.Select(x => x.Value).ToList();
|
||||
|
||||
foreach (var craft in craftList)
|
||||
{
|
||||
var craft_attribute = craft.getOriginEntityAttribute<CraftAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_attribute, () => $"craft_attribute is null !!!");
|
||||
|
||||
craft_attribute.CraftFinishTime = DateTimeHelper.Current;
|
||||
craft_attribute.modifiedEntityAttribute();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
356
GameServer/Contents/Craft/Action/CraftHelpAction.cs
Normal file
356
GameServer/Contents/Craft/Action/CraftHelpAction.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
using ANCHOR_GUID = System.String;
|
||||
using USER_GUID = System.String;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using GameServer.PacketHandler;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class CraftHelpAction : EntityActionBase
|
||||
{
|
||||
public CraftHelpAction(Player owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public async Task<Result> CraftHelpProcess(ANCHOR_GUID anchor_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var crafting_anchor = game_zone_action.GetAnchor(anchor_guid);
|
||||
if (crafting_anchor == null)
|
||||
{
|
||||
err_msg = $"anchor is not placed !!! - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingAnchorIsNotPlaced, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var room_id = player.getCurrentInstanceRoomId();
|
||||
result = MyhomeHelper.getMyhomeOwnerUserGuidAndMyhomeGuidFromRoomId(room_id, out var target_guid, out var myhome_guid);
|
||||
|
||||
var fn_craft_help = async delegate ()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
|
||||
//대상 CraftDoc의 FinishTime값 변경
|
||||
(result, var target_craft_doc) = await changeTargetCraftTime(target_guid, anchor_guid);
|
||||
if (result.isFail()) { HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result); return result; }
|
||||
NullReferenceCheckHelper.throwIfNull(target_craft_doc, () => $"target_craft_doc is null !!! - {player.toBasicString()}");
|
||||
|
||||
var craft_attrib = target_craft_doc.getAttrib<CraftAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_attrib, () => $"craft_attrib is null !!! - {player.toBasicString()}");
|
||||
|
||||
var finish_time = Timestamp.FromDateTime(craft_attrib.CraftFinishTime);
|
||||
|
||||
var task_craft_log_data = CraftBusinessLogHelper.toCraftLogInfo(craft_attrib);
|
||||
invokers.Add(new CraftBusinessLog(task_craft_log_data));
|
||||
|
||||
//나의 CraftHelpDoc 변경
|
||||
result = changeCraftHelp(target_guid);
|
||||
if (result.isFail()) { HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result); return result; }
|
||||
|
||||
var craft_help_attribute = player.getEntityAttribute<CraftHelpAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_help_attribute, () => $"craft_help_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
var task_log_data = CraftBusinessLogHelper.toCraftHelpLogInfo(craft_help_attribute);
|
||||
invokers.Add(new CraftHelpBusinessLog(task_log_data));
|
||||
|
||||
//대상 CraftHelpDoc 변경
|
||||
(result, var target_craft_help_doc) = await changeTargetCraftHelp(target_guid);
|
||||
if (result.isFail()) { HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result); return result; }
|
||||
NullReferenceCheckHelper.throwIfNull(target_craft_help_doc, () => $"target_craft_help_doc is null !!! - {player.toBasicString()}");
|
||||
|
||||
var target_craft_help_attrib = target_craft_help_doc.getAttrib<CraftHelpAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(target_craft_help_attrib, () => $"target_craft_help_attrib is null !!! - {player.toBasicString()}");
|
||||
|
||||
var task_target_log_data = CraftBusinessLogHelper.toCraftHelpLogInfo(target_craft_help_attrib);
|
||||
invokers.Add(new CraftHelpBusinessLog(task_target_log_data));
|
||||
|
||||
//도움 보상 처리
|
||||
(result, var received_item_list) = await TakeHelpReward();
|
||||
if (result.isFail()) { HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result); return result; }
|
||||
|
||||
//동기화를 위한 redis작업
|
||||
var request = new CraftHelpCacheRequest(player, server_logic.getRedisConnector(), target_guid);
|
||||
result = await request.UpsertCraftHelp(player.getUserGuid());
|
||||
if (result.isFail()) { HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result); return result; }
|
||||
|
||||
//타 서버 패킷 전송을 위한 데이터 받아오기
|
||||
(result, var myhome_instance_room_infos) = await getInstanceRoomInfos(target_guid, myhome_guid);
|
||||
if (result.isFail()) { HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result); return result; }
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CraftHelp
|
||||
, dynamo_db_client, true);
|
||||
{
|
||||
batch.addQuery(new DBQEntityWrite(new List<DynamoDbDocBase>() { target_craft_help_doc, target_craft_doc }));
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(invokers);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HelpCraftPacketHandler.send_S2C_ACK_HELP_CRAFT(player, result, received_item_list, craft_help_attribute.HelpUserGuids.Count);
|
||||
game_zone_action.broadcast(player, CraftNotifyHelper.makeNtfCraftUpdatePacket(anchor_guid, finish_time));
|
||||
|
||||
var player_manager = server_logic.getPlayerManager();
|
||||
if (player_manager.tryGetUserByPrimaryKey(target_guid, out var found_user) == true)
|
||||
{
|
||||
var craft_action = found_user.getEntityAction<CraftAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_action, () => $"craft_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
craft_action.setUpdateCraft(true);
|
||||
}
|
||||
|
||||
foreach (var myhome_instance_room_info in myhome_instance_room_infos)
|
||||
{
|
||||
var server_name = ServerBase.ServerHelper.makeServerNameByNetworkAddress(ServerType.Indun, myhome_instance_room_info.InstanceAddress, (ushort)myhome_instance_room_info.InstancePort);
|
||||
CraftNotifyHelper.send_GS2GS_NTF_CraftUpdate(server_name, room_id, anchor_guid, finish_time, target_guid, target_craft_help_attrib.HelpedUserGuids.Count, player.getUserNickname());
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CraftHelp", fn_craft_help);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<(Result, List<InstanceRoomInfo>)> getInstanceRoomInfos(string myhomeOwnerGuid, string myhomeGuid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var myhome_instance_room_infos = new List<InstanceRoomInfo>();
|
||||
|
||||
(result, myhome_instance_room_infos) = await InstanceRoomHandler.tryGetMyhomeInstanceRoomInfos(myhomeOwnerGuid, myhomeGuid);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to tryGetMyhomeServers() !!! : {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return (result, myhome_instance_room_infos);
|
||||
}
|
||||
|
||||
return (result, myhome_instance_room_infos);
|
||||
}
|
||||
|
||||
public async Task<(Result, List<Item>)> TakeHelpReward()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
||||
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var received_item_list = new List<Item>();
|
||||
(result, var new_item_list) = await inventory_action.tryTakalbleToBag((META_ID)MetaHelper.GameConfigMeta.CraftingHelpGetItemId, (ushort)MetaHelper.GameConfigMeta.CraftingHelpGetItemValue);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, received_item_list);
|
||||
}
|
||||
received_item_list.AddRange(new_item_list);
|
||||
|
||||
return (result, received_item_list);
|
||||
}
|
||||
|
||||
public async Task<(Result, DynamoDbDocBase?)> changeTargetCraftTime(USER_GUID target_guid, ANCHOR_GUID anchor_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
|
||||
var doc = new CraftDoc(target_guid, anchor_guid);
|
||||
var query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(doc.getPK(), doc.getSK());
|
||||
|
||||
(result, var target_craft_docs) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig<CraftDoc>(query_config);
|
||||
if (target_craft_docs.Count == 0)
|
||||
{
|
||||
err_msg = $"Crafting Doc is empty !!! target userGuid:{target_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftDocIsEmpty, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var target_craft_attrib = target_craft_docs[0].getAttrib<CraftAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(target_craft_attrib, () => $"target_craft_attrib is null !!!");
|
||||
|
||||
if (target_craft_attrib.CraftFinishTime <= DateTimeHelper.Current)
|
||||
{
|
||||
err_msg = $"Crafting Already Finish, can't help the craft !!! : target guid :{target_guid} anchor_guid :{anchor_guid}- {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingAlreadyFinish, err_msg);
|
||||
Log.getLogger().info(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
target_craft_attrib.CraftFinishTime = target_craft_attrib.CraftFinishTime.AddMinutes(MetaHelper.GameConfigMeta.CraftingHelpReduceTime * -1);
|
||||
|
||||
target_craft_docs[0].setQueryType(QueryType.Update);
|
||||
|
||||
return (result, target_craft_docs[0]);
|
||||
}
|
||||
|
||||
public Result changeCraftHelp(USER_GUID target_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var craft_help_attribute = player.getEntityAttribute<CraftHelpAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_help_attribute, () => $"craft_help_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
if (craft_help_attribute.CraftHelpUpdateDay < DateTime.UtcNow.Date)
|
||||
{
|
||||
craft_help_attribute.HelpUserGuids.Clear();
|
||||
craft_help_attribute.HelpedUserGuids.Clear();
|
||||
craft_help_attribute.CraftHelpUpdateDay = DateTime.UtcNow.Date;
|
||||
craft_help_attribute.modifiedEntityAttribute();
|
||||
}
|
||||
|
||||
int same_User_Count = 1;
|
||||
foreach (var user_guid in craft_help_attribute.HelpUserGuids)
|
||||
{
|
||||
if (user_guid == target_guid)
|
||||
{
|
||||
same_User_Count += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (craft_help_attribute.HelpUserGuids.Count >= MetaHelper.GameConfigMeta.CraftingHelpLimitCount)
|
||||
{
|
||||
err_msg = $"Crafting help Count Over !!! - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingHelpCountOver, err_msg);
|
||||
Log.getLogger().info(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (same_User_Count > MetaHelper.GameConfigMeta.CraftingHelpLimitCountSameUser)
|
||||
{
|
||||
err_msg = $"Crafting help Same User Count Over !!! : target guid :{target_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingHelpSameUserCountOver, err_msg);
|
||||
Log.getLogger().info(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
craft_help_attribute.HelpUserGuids.Add(target_guid);
|
||||
craft_help_attribute.modifiedEntityAttribute();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<(Result, DynamoDbDocBase?)> changeTargetCraftHelp(USER_GUID target_guid)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
|
||||
var doc = new CraftHelpDoc(target_guid);
|
||||
var query_config = dynamo_db_client.makeQueryConfigForReadByPKOnly(doc.getPK());
|
||||
|
||||
(result, var read_docs) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig<CraftHelpDoc>(query_config);
|
||||
if (read_docs.Count == 0)
|
||||
{
|
||||
err_msg = $"Crafting help Doc is empty !!! target userGuid:{target_guid} - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftHelpDocIsEmpty, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var target_craft_help_attrib = read_docs[0].getAttrib<CraftHelpAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(target_craft_help_attrib, () => $"pltarget_craft_help_attribayer is null !!! - {player.toBasicString()}");
|
||||
|
||||
if (target_craft_help_attrib.CraftHelpUpdateDay < DateTime.UtcNow.Date)
|
||||
{
|
||||
target_craft_help_attrib.HelpUserGuids.Clear();
|
||||
target_craft_help_attrib.HelpedUserGuids.Clear();
|
||||
}
|
||||
|
||||
if (target_craft_help_attrib.HelpedUserGuids.Count >= MetaHelper.GameConfigMeta.CraftingHelpLimitCountReceive)
|
||||
{
|
||||
err_msg = $"Crafting help Same User Count Over !!! : target guid :{target_guid}- {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingHelpReceivedCountOver, err_msg);
|
||||
Log.getLogger().info(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
target_craft_help_attrib.HelpedUserGuids.Add(player.getUserGuid());
|
||||
target_craft_help_attrib.CraftHelpUpdateDay = DateTime.UtcNow.Date;
|
||||
|
||||
read_docs[0].setQueryType(QueryType.Update);
|
||||
|
||||
return (result, read_docs[0]);
|
||||
}
|
||||
|
||||
public Result cheatChangeCraftHelpInit()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var craft_help_attribute = player.getEntityAttribute<CraftHelpAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_help_attribute, () => $"craft_help_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
craft_help_attribute.HelpUserGuids.Clear();
|
||||
craft_help_attribute.HelpedUserGuids.Clear();
|
||||
craft_help_attribute.CraftHelpUpdateDay = DateTime.UtcNow.Date;
|
||||
craft_help_attribute.modifiedEntityAttribute();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
119
GameServer/Contents/Craft/Action/CraftRecipeAction.cs
Normal file
119
GameServer/Contents/Craft/Action/CraftRecipeAction.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using Amazon.S3.Model.Internal.MarshallTransformations;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class CraftRecipeAction : EntityActionBase
|
||||
{
|
||||
private ConcurrentDictionary<META_ID, CraftRecipe> m_Recipes = new();
|
||||
|
||||
public CraftRecipeAction(Player owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
m_Recipes.Clear();
|
||||
}
|
||||
|
||||
public List<META_ID> getRecipeMetaIds()
|
||||
{
|
||||
var recipe_meta_ids = new List<META_ID>();
|
||||
|
||||
foreach (var recipe in m_Recipes.Values)
|
||||
{
|
||||
var recipe_attribute = recipe.getEntityAttribute<CraftRecipeAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(recipe_attribute, () => $"recipe_attribute is null !!!");
|
||||
|
||||
recipe_meta_ids.Add(recipe_attribute.CraftMetaId);
|
||||
}
|
||||
|
||||
return recipe_meta_ids;
|
||||
}
|
||||
|
||||
public async Task<Result> AddRecipeFromDocs(List<CraftRecipeDoc> recipeDocs)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
foreach (var recipe_doc in recipeDocs)
|
||||
{
|
||||
(result, var recipe) = await CraftRecipe.createRecipeFromDoc(player, recipe_doc);
|
||||
if (result.isFail() || recipe == null)
|
||||
{
|
||||
err_msg = $"Failed to createRecipeFromDoc() !!! : {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var recipe_attribute = recipe.getEntityAttribute<CraftRecipeAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(recipe_attribute, () => $"recipe_attribute is null !!! - {player.toBasicString()}");
|
||||
|
||||
if (m_Recipes.TryAdd(recipe_attribute.CraftMetaId, recipe) == false)
|
||||
{
|
||||
err_msg = $"Failed to get recipe attribute : {nameof(CraftRecipeAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> RegisterRecipe(META_ID craft_meta_id)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
if (HasRecipe(craft_meta_id) == true)
|
||||
{
|
||||
err_msg = $"Already Registered Recipe Failed. !!! - {getOwner().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingRecipeIsAlreadyRegister, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, var craft_recipe) = await CraftRecipe.createRecipe(player, craft_meta_id);
|
||||
if (result.isFail() || craft_recipe == null)
|
||||
{
|
||||
err_msg = $"Create Craft Recipe Failed. !!! - {getOwner().toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
m_Recipes.TryAdd(craft_meta_id, craft_recipe);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool HasRecipe(META_ID craft_meta_id)
|
||||
{
|
||||
if(m_Recipes.TryGetValue(craft_meta_id, out var result) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
120
GameServer/Contents/Craft/Craft.cs
Normal file
120
GameServer/Contents/Craft/Craft.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using BEACON_GUID = System.String;
|
||||
using META_ID = System.UInt32;
|
||||
using ANCHOR_GUID = System.String;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class Craft : EntityBase
|
||||
{
|
||||
public Craft(EntityBase parent)
|
||||
: base(EntityType.Craft, parent)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
var direct_parent = getDirectParent();
|
||||
NullReferenceCheckHelper.throwIfNull(direct_parent, () => $"direct_parent is null !!!");
|
||||
addEntityAttribute(new CraftAttribute(this, direct_parent));
|
||||
return await base.onInit();
|
||||
}
|
||||
|
||||
public override string toBasicString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public override string toSummaryString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public static async Task<(Result, Craft?)> createCraftFromDoc(EntityBase parent, CraftDoc doc)
|
||||
{
|
||||
var craft = new Craft(parent);
|
||||
var result = await craft.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var craft_attribute = craft.getEntityAttribute<CraftAttribute>();
|
||||
if (craft_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get craft attribute : {nameof(CraftAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (craft_attribute.copyEntityAttributeFromDoc(doc) == false)
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromDoc !!! : doc_type {doc.GetType()} - {craft.getRootParent().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, craft);
|
||||
}
|
||||
|
||||
public static async Task<(Result, Craft?)> createCraft(EntityBase parent, ANCHOR_GUID anchor_guid, META_ID craft_meta_id, BEACON_GUID beacon_guid, DateTime now, DateTime craft_finish_time, int craft_count)
|
||||
{
|
||||
var craft = new Craft(parent);
|
||||
var result = await craft.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var craft_attribute = craft.getEntityAttribute<CraftAttribute>();
|
||||
if (craft_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get craft attribute : {nameof(CraftAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
craft_attribute.AnchorGuid = anchor_guid;
|
||||
craft_attribute.CraftMetaId = craft_meta_id;
|
||||
craft_attribute.CraftStartTime = now;
|
||||
craft_attribute.CraftFinishTime = craft_finish_time;
|
||||
craft_attribute.BeaconGuid = beacon_guid;
|
||||
craft_attribute.CraftCount = craft_count;
|
||||
|
||||
craft_attribute.newEntityAttribute();
|
||||
|
||||
return (result, craft);
|
||||
}
|
||||
|
||||
public CraftInfo toCraftData4Client()
|
||||
{
|
||||
var craft_4_client = new CraftInfo();
|
||||
|
||||
var craft_attribute = getEntityAttribute<CraftAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_attribute, () => $"craft_attribute is null !!!");
|
||||
|
||||
craft_4_client.AnchorGuid = craft_attribute.AnchorGuid;
|
||||
craft_4_client.CraftMetaId = (int)craft_attribute.CraftMetaId;
|
||||
craft_4_client.CraftStartTime = new Timestamp();
|
||||
if (craft_attribute.CraftStartTime != new DateTime())
|
||||
{
|
||||
craft_4_client.CraftStartTime = Timestamp.FromDateTime(craft_attribute.CraftStartTime);
|
||||
}
|
||||
craft_4_client.CraftFinishTime = Timestamp.FromDateTime(craft_attribute.CraftFinishTime);
|
||||
craft_4_client.BeaconGuid = craft_attribute.BeaconGuid;
|
||||
craft_4_client.CraftCount = craft_attribute.CraftCount;
|
||||
|
||||
return craft_4_client;
|
||||
}
|
||||
}
|
||||
}
|
||||
144
GameServer/Contents/Craft/CraftCheat.cs
Normal file
144
GameServer/Contents/Craft/CraftCheat.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
[ChatCommandAttribute("crafthelpinit", typeof(CheatCraftHelpInit), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatCraftHelpInit : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CraftHelpInit");
|
||||
|
||||
var craft_help_action = player.getEntityAction<CraftHelpAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_help_action, () => $"craft_help_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var fn_start = async delegate ()
|
||||
{
|
||||
craft_help_action.cheatChangeCraftHelpInit();
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CheatCommandCraftHelpInit
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
var result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var transaction_name = "CheatCommandCraftHelpInit";
|
||||
var result = await player.runTransactionRunnerSafelyWithTransGuid(player.getUserGuid()
|
||||
, TransactionIdType.PrivateContents, transaction_name
|
||||
, fn_start);
|
||||
if (result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to runTransactionRunnerSafelyWithTransGuid() !!! : {result.toBasicString()} - transactionName:{transaction_name}, {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("registercraftrecipe", typeof(CheatRegisterCraftRecipe), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatRegisterCraftRecipe : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatRegisterCraftRecipe");
|
||||
|
||||
var craft_recipe_action = player.getEntityAction<CraftRecipeAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_recipe_action, () => $"craft_recipe_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Log.getLogger().error($"Invalid Argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (uint.TryParse(args[0], out uint recipe_meta_id) == false)
|
||||
return;
|
||||
|
||||
var fn_start = async delegate ()
|
||||
{
|
||||
var result = await craft_recipe_action.RegisterRecipe(recipe_meta_id);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CheatCommandRegisterCraftRecipe
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var transaction_name = "Cheat.CommandRegisterCraftRecipe";
|
||||
var result = await player.runTransactionRunnerSafelyWithTransGuid(player.getUserGuid()
|
||||
, TransactionIdType.PrivateContents, transaction_name
|
||||
, fn_start);
|
||||
if (result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to runTransactionRunnerSafelyWithTransGuid() !!! : {result.toBasicString()} - transactionName:{transaction_name}, {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ChatCommandAttribute("craftfinish", typeof(CheatAllCraftFinish), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class CheatAllCraftFinish : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
Log.getLogger().info($"CheatAllCraftFinish");
|
||||
|
||||
var craft_action = player.getEntityAction<CraftAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_action, () => $"craft_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var fn_start = async delegate ()
|
||||
{
|
||||
var result = craft_action.cheatAllCraftFinish();
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.CheatAllCraftFinish
|
||||
, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
}
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var transaction_name = "Cheat.CommandAllCraftFinish";
|
||||
var result = await player.runTransactionRunnerSafelyWithTransGuid(player.getUserGuid()
|
||||
, TransactionIdType.PrivateContents, transaction_name
|
||||
, fn_start);
|
||||
if (result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to runTransactionRunnerSafelyWithTransGuid() !!! : {result.toBasicString()} - transactionName:{transaction_name}, {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
93
GameServer/Contents/Craft/CraftRecipe.cs
Normal file
93
GameServer/Contents/Craft/CraftRecipe.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using Amazon.S3.Model;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class CraftRecipe : EntityBase
|
||||
{
|
||||
public CraftRecipe(EntityBase parent)
|
||||
: base(EntityType.Recipe, parent)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Result> onInit()
|
||||
{
|
||||
var parent = getDirectParent();
|
||||
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
||||
|
||||
addEntityAttribute(new CraftRecipeAttribute(this, parent));
|
||||
return await base.onInit();
|
||||
}
|
||||
|
||||
public override string toBasicString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public override string toSummaryString()
|
||||
{
|
||||
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
|
||||
}
|
||||
|
||||
public static async Task<(Result, CraftRecipe?)> createRecipeFromDoc(EntityBase parent, CraftRecipeDoc doc)
|
||||
{
|
||||
var recipe = new CraftRecipe(parent);
|
||||
var result = await recipe.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var recipe_attribute = recipe.getEntityAttribute<CraftRecipeAttribute>();
|
||||
if (recipe_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get recipe attribute : {nameof(CraftRecipeAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (recipe_attribute.copyEntityAttributeFromDoc(doc) == false)
|
||||
{
|
||||
err_msg = $"Failed to copyEntityAttributeFromDoc !!! : doc_type {doc.GetType()} - {recipe.getRootParent().toBasicString()}";
|
||||
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, recipe);
|
||||
}
|
||||
|
||||
public static async Task<(Result, CraftRecipe?)> createRecipe(EntityBase parent, META_ID craft_meta_id)
|
||||
{
|
||||
var recipe = new CraftRecipe(parent);
|
||||
var result = await recipe.onInit();
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var recipe_attribute = recipe.getEntityAttribute<CraftRecipeAttribute>();
|
||||
if (recipe_attribute == null)
|
||||
{
|
||||
err_msg = $"Failed to get recipe attribute : {nameof(CraftRecipeAttribute)}";
|
||||
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
recipe_attribute.CraftMetaId = craft_meta_id;
|
||||
|
||||
recipe_attribute.newEntityAttribute();
|
||||
|
||||
return (result, recipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
106
GameServer/Contents/Craft/DBQuery/DBQCraftReadAll.cs
Normal file
106
GameServer/Contents/Craft/DBQuery/DBQCraftReadAll.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class DBQCraftReadAll : QueryExecutorBase
|
||||
{
|
||||
private string m_combination_key_for_pk = string.Empty;
|
||||
|
||||
private string m_craft_pk = string.Empty;
|
||||
|
||||
private readonly List<CraftDoc> m_to_read_craft_docs = new();
|
||||
|
||||
public DBQCraftReadAll(string combinationKeyForPK)
|
||||
: base(typeof(DBQCraftReadAll).Name)
|
||||
{
|
||||
m_combination_key_for_pk = combinationKeyForPK;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//=====================================================================================
|
||||
public override Task<Result> onPrepareQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var craft_doc = new CraftDoc();
|
||||
craft_doc.setCombinationKeyForPK(m_combination_key_for_pk);
|
||||
|
||||
var error_code = craft_doc.onApplyPKSK();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(error_code, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
m_craft_pk = craft_doc.getPK();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var query_batch = getQueryBatch();
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => "query_batch is null !!!");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
var craft_query_config = db_connector.makeQueryConfigForReadByPKOnly(m_craft_pk);
|
||||
|
||||
var craft_action = owner.getEntityAction<CraftAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_action, () => "craft_action is null !!!");
|
||||
|
||||
(result, var craft_read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<CraftDoc>(craft_query_config, eventTid: query_batch.getTransId());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await craft_action.AddCraftFromDocs(craft_read_docs);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
m_to_read_craft_docs.AddRange(craft_read_docs);
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
public List<CraftDoc> getToReadItemDocs() => m_to_read_craft_docs;
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseCommit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
public new Player? getOwner() => getQueryBatch()?.getLogActor() as Player;
|
||||
}
|
||||
}
|
||||
104
GameServer/Contents/Craft/DBQuery/DBQCraftRecipeReadAll.cs
Normal file
104
GameServer/Contents/Craft/DBQuery/DBQCraftRecipeReadAll.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class DBQCraftRecipeReadAll : QueryExecutorBase
|
||||
{
|
||||
private string m_combination_key_for_pk = string.Empty;
|
||||
|
||||
private string m_craft_recipe_pk = string.Empty;
|
||||
|
||||
private readonly Dictionary<META_ID, CraftRecipeDoc> m_to_read_craft_recipe_docs = new();
|
||||
|
||||
public DBQCraftRecipeReadAll(string combinationKeyForPK)
|
||||
: base(typeof(DBQCraftRecipeReadAll).Name)
|
||||
{
|
||||
m_combination_key_for_pk = combinationKeyForPK;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
|
||||
//=====================================================================================
|
||||
public override Task<Result> onPrepareQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var recipe_doc = new CraftRecipeDoc();
|
||||
recipe_doc.setCombinationKeyForPK(m_combination_key_for_pk);
|
||||
|
||||
var error_code = recipe_doc.onApplyPKSK();
|
||||
if (error_code.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(error_code, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
m_craft_recipe_pk = recipe_doc.getPK();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// onPrepareQuery()를 성공할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task<Result> onQuery()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
||||
|
||||
var query_batch = getQueryBatch();
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => "query_batch is null !!!");
|
||||
|
||||
var db_connector = query_batch.getDynamoDbConnector();
|
||||
var craft_recipe_query_config = db_connector.makeQueryConfigForReadByPKOnly(m_craft_recipe_pk);
|
||||
|
||||
var craft_recipe_action = owner.getEntityAction<CraftRecipeAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(craft_recipe_action, () => "craft_recipe_action is null !!!");
|
||||
|
||||
(result, var craft_recipe_read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<CraftRecipeDoc>(craft_recipe_query_config, eventTid: query_batch.getTransId());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await craft_recipe_action.AddRecipeFromDocs(craft_recipe_read_docs);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
|
||||
public Dictionary<META_ID, CraftRecipeDoc> getToReadItemDocs() => m_to_read_craft_recipe_docs;
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseCommit()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
|
||||
//=====================================================================================
|
||||
public override async Task onQueryResponseRollback(Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
public new Player? getOwner() => getQueryBatch()?.getLogActor() as Player;
|
||||
}
|
||||
}
|
||||
31
GameServer/Contents/Craft/Helper/CraftHelper.cs
Normal file
31
GameServer/Contents/Craft/Helper/CraftHelper.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
internal static class CraftHelper
|
||||
{
|
||||
public static Result checkAnchorCrafting(Player player, List<string> anchorGuids)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var crafting_action = player.getEntityAction<CraftAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(crafting_action, () => $"crafting_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
foreach (var anchor_guid in anchorGuids)
|
||||
{
|
||||
if (crafting_action.isAnchorCrafting(anchor_guid))
|
||||
{
|
||||
err_msg = $"Anchor is Already Crafting !!! : AnchorGuid:{anchor_guid} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.CraftingAlreadyCrafting, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
GameServer/Contents/Craft/Log/CraftBusinessLog.cs
Normal file
32
GameServer/Contents/Craft/Log/CraftBusinessLog.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class CraftBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private CraftLogData m_data_to_log;
|
||||
public CraftBusinessLog(CraftLogData log_data_param)
|
||||
: base(LogDomainType.Craft)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new CraftLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
83
GameServer/Contents/Craft/Log/CraftBusinessLogHelper.cs
Normal file
83
GameServer/Contents/Craft/Log/CraftBusinessLogHelper.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using ServerCommon;
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
static public class CraftBusinessLogHelper
|
||||
{
|
||||
static public CraftLogData toCraftLogInfo(CraftAttribute craftAttribute)
|
||||
{
|
||||
var logData = new CraftLogData();
|
||||
logData.setCraftInfo(craftAttribute);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public CraftLogData toCraftLogInfo(CraftAttrib craftAttrib)
|
||||
{
|
||||
var logData = new CraftLogData();
|
||||
logData.setCraftInfo(craftAttrib);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setCraftInfo(this CraftLogData logData, CraftAttribute craftAttribute)
|
||||
{
|
||||
logData.AnchorGuid = craftAttribute.AnchorGuid;
|
||||
logData.CraftMetaId = craftAttribute.CraftMetaId;
|
||||
logData.CraftStartTime = craftAttribute.CraftStartTime;
|
||||
logData.CraftFinishTime = craftAttribute.CraftFinishTime;
|
||||
logData.BeaconGuid = craftAttribute.BeaconGuid;
|
||||
logData.CraftCount = craftAttribute.CraftCount;
|
||||
}
|
||||
|
||||
static public void setCraftInfo(this CraftLogData logData, CraftAttrib craftAttrib)
|
||||
{
|
||||
logData.AnchorGuid = craftAttrib.AnchorGuid;
|
||||
logData.CraftMetaId = craftAttrib.CraftMetaId;
|
||||
logData.CraftStartTime = craftAttrib.CraftStartTime;
|
||||
logData.CraftFinishTime = craftAttrib.CraftFinishTime;
|
||||
logData.BeaconGuid = craftAttrib.BeaconGuid;
|
||||
logData.CraftCount = craftAttrib.CraftCount;
|
||||
}
|
||||
|
||||
static public CraftHelpLogData toCraftHelpLogInfo(CraftHelpAttrib craftHelpAttrib)
|
||||
{
|
||||
var logData = new CraftHelpLogData();
|
||||
logData.setCraftHelpInfo(craftHelpAttrib);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public CraftHelpLogData toCraftHelpLogInfo(CraftHelpAttribute craftHelpAttribute)
|
||||
{
|
||||
var logData = new CraftHelpLogData();
|
||||
logData.setCraftHelpInfo(craftHelpAttribute);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setCraftHelpInfo(this CraftHelpLogData logData, CraftHelpAttrib craftHelpAttrib)
|
||||
{
|
||||
logData.HelpUserGuids = craftHelpAttrib.HelpUserGuids;
|
||||
logData.HelpedUserGuids = craftHelpAttrib.HelpedUserGuids;
|
||||
logData.CraftHelpUpdateDay = craftHelpAttrib.CraftHelpUpdateDay;
|
||||
}
|
||||
|
||||
static public void setCraftHelpInfo(this CraftHelpLogData logData, CraftHelpAttribute craftHelpAttribute)
|
||||
{
|
||||
logData.HelpUserGuids = craftHelpAttribute.HelpUserGuids;
|
||||
logData.HelpedUserGuids = craftHelpAttribute.HelpedUserGuids;
|
||||
logData.CraftHelpUpdateDay = craftHelpAttribute.CraftHelpUpdateDay;
|
||||
}
|
||||
|
||||
static public CraftRecipeLogData toCraftRecipeLogInfo(int recipe_meta_id)
|
||||
{
|
||||
var logData = new CraftRecipeLogData();
|
||||
logData.setCraftRecipeInfo(recipe_meta_id);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setCraftRecipeInfo(this CraftRecipeLogData logData, int recipe_meta_id)
|
||||
{
|
||||
logData.recipe_meta_id = (META_ID)recipe_meta_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user