using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using NeoSmart.AsyncLock; using Google.Protobuf.WellKnownTypes; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using ServerCore; using ServerBase; using META_ID = System.UInt32; namespace ServerCommon { public class BuffAttribute : EntityAttributeBase, ICopyEntityAttributeFromCache { public class BuffInfo { [JsonProperty] public META_ID BuffMetaID { get; set; } = 0; [JsonProperty] public DateTime BuffStartTime { get; set; } = new(); public BuffInfo() { } public BuffInfo(BuffInfo buffInfo) { BuffMetaID = buffInfo.BuffMetaID; BuffStartTime = buffInfo.BuffStartTime; } } [JsonProperty] public Dictionary> BuffInfos = new(); private AsyncLock m_lock = new(); public BuffAttribute(EntityBase owner) : base(owner) { foreach (MetaAssets.EBuffCategory category in System.Enum.GetValues(typeof(MetaAssets.EBuffCategory))) { var buff_channel_Info = new Dictionary(); BuffInfos.TryAdd(category, buff_channel_Info); } } public override void onClear() { foreach(var buff_infos in BuffInfos.Values) { buff_infos.Clear(); } } public bool copyEntityAttributeFromCache(CacheBase cacheBase) { var result = new Result(); var err_msg = string.Empty; var to_cast_string = typeof(BuffCache).Name; var buff_cache = cacheBase as BuffCache; if (null == buff_cache) { err_msg = $"Failed to copyEntityAttributeFromCache() !!!, buff_cache is null :{to_cast_string}"; Log.getLogger().error(err_msg); return false; } //===================================================================================== // Cache => Attribute //===================================================================================== foreach(var channel_buff in buff_cache.buff_cache_Infos) { foreach(var buff_info_cache in channel_buff.Value) { if (false == MetaData.Instance._BuffTable.TryGetValue((int)buff_info_cache.Value.BuffMetaID, out var buffMetaData)) { err_msg = $"Not found BuffMeta !!! : buffMetaId:{buff_info_cache.Value.BuffMetaID}"; result.setFail(ServerErrorCode.BuffMetaDataNotFound, err_msg); Log.getLogger().error(result.toBasicString()); continue; } if (BuffInfos.TryGetValue(channel_buff.Key, out var attribute_channel_buffs) == false) { attribute_channel_buffs = new Dictionary(); BuffInfos.TryAdd(channel_buff.Key, attribute_channel_buffs); } var buff = new BuffInfo(); buff.BuffMetaID = buff_info_cache.Value.BuffMetaID; buff.BuffStartTime = buff_info_cache.Value.BuffStartTime; attribute_channel_buffs.TryAdd(buff_info_cache.Key, buff); { err_msg = $"Duplicated buff in channel !!! : buffMetaId:{buff_info_cache.Value.BuffMetaID}"; result.setFail(ServerErrorCode.BuffCacheLoadDuplicatedBuff, err_msg); Log.getLogger().error(result.toBasicString()); continue; } } } return true; } public bool AddBuff(MetaAssets.EBuffCategory eBuffCategory, int channel, int buffId, [MaybeNullWhen(false)] out BuffInfo addBuff) { addBuff = null; if (BuffInfos.TryGetValue(eBuffCategory, out var buffchannelInfo) == false) { return false; } var buff = new BuffInfo(); buff.BuffMetaID = (META_ID)buffId; buff.BuffStartTime = DateTimeHelper.Current; using (m_lock.Lock()) { if (buffchannelInfo.TryAdd(channel, buff) == false) { return false; } } addBuff = buff; return true; } public bool RemoveBuff(MetaAssets.EBuffCategory eBuffCategory, int channel, [MaybeNullWhen(false)] out BuffInfo delBuff) { delBuff = null; if (BuffInfos.TryGetValue(eBuffCategory, out var buffchannelInfo) == false) { return false; } using (m_lock.Lock()) { if (buffchannelInfo.Remove(channel, out delBuff) == false) { return false; } } return true; } public override EntityAttributeBase onCloned() { var buff_attribute = new BuffAttribute(getOwner()); foreach (var buff_channels in BuffInfos) { buff_attribute.BuffInfos[buff_channels.Key] = new Dictionary(buff_channels.Value.ToDictionary(a => a.Key, b => new BuffInfo(b.Value))); } return buff_attribute; } public override IEntityAttributeTransactor onNewEntityAttributeTransactor() { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var player = owner.getRootParent() as UserBase; NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!"); return new BuffAttributeTransactor(player); } } public class BuffAttributeTransactor : EntityAttributeTransactorBase { public BuffAttributeTransactor(UserBase owner) : base(owner) { } } }