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 onInit() { await Task.CompletedTask; var result = new Result(); return result; } public async Task 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(); 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() { 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(); 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(); 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(); 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(); 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 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(); 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(); var invokers = new List(); 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 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() { 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(); 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(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 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(); 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 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(); 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 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(); 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(); var buff_attribute = player.getOriginEntityAttribute(); 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; } } }