using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sog; using ProtoCSStruct; using System.Threading; using TencentCloud.Cdn.V20180606.Models; namespace Chat { public class SysNoticeSvc : BaseReloadableService { public static long m_lastTickTime = 0 ; //配置文件被重新加载 public static void OnReloadConfig(string excelConfigFile) { if (string.IsNullOrEmpty(excelConfigFile) || excelConfigFile == "SysNoticeDesc.bin" || excelConfigFile == "SysNoticeDesc.txt") { //重新加载配置 LoadOnServerStart(); } } public static void LoadOnServerStart() { //清空老的 ChatServerUtils.GetChatServerData().m_sysNoticeList.Clear(); // SortedList descList = SysNoticeDescMgr.Instance.ItemTable; // TraceLog.Debug("SysNoticeUtils.LoadOnServerStart begin, desc count {0}", descList.Count); // foreach (SysNoticeDesc desc in descList.Values) // { // if (desc.state != 1) //未开启忽略 // { // continue; // } // long startTime = ConfigStringTimeParse.ParseConfigTime(desc.startTime); // long endTime = ConfigStringTimeParse.ParseConfigTime(desc.endTime); // AddOneSysNotice(startTime, endTime, desc); // // } ChatServerUtils.GetChatServerData().m_noticeBackgrounds.Clear(); } public static void OnNoticeBackGgoundsTick(long nowMs) { if (nowMs - m_lastTickTime < 60000) { return; } m_lastTickTime = nowMs; // 向 operationServer 请求背景图数据 SSNoticeBackGroundsReq backgroungdReq = new SSNoticeBackGroundsReq(); backgroungdReq.Language.SetString(""); ChatServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.NoticeBackgroundsReq, ref backgroungdReq, 0); } public static void ReloadByID(uint id) { } /// ///检查公告是否有效 /// /// /// public static Tuple CheckSysNotice(int ID, int playerRealmID) { long timeSecond = ChatServerUtils.GetTimeSecond(); var noticeObj = ChatServerUtils.GetChatServerData().m_sysNoticeList.Find(f => f.notice.Id == ID); var _ServerData = ChatServerUtils.GetChatServerData(); ///服务器列表 var allRealm = _ServerData.m_allRealmMap; RealmBriefInfo curRealm = null; try { allRealm.TryGetValue(playerRealmID, out curRealm); } catch (Exception) { TraceLog.Error("SysNoticeSvc.CheckSysNotice get RealmBriefInfo by Id : playerRealmID :{0}", playerRealmID); } if (curRealm != null) { int realmTimeZone = curRealm.timeZone; long diffTimeZone = (AppTime.TimeZone - realmTimeZone) * 3600; timeSecond += diffTimeZone; } Tuple failres = new Tuple(false, 0, 0); if (noticeObj == null || noticeObj.notice.Id == 0) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice not found id={0}", ID); return failres; } //公告被禁用 if (noticeObj.notice.State != 1) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice id={0} state dont 1", ID); return failres; } //公告不是针对全服 bool isRealm = true; // 旧的公告判断方法 if (noticeObj.notice.Realmlist.Count != 0 && noticeObj.notice.Realmlist[0] != 0) { //在公告服务器列表中找到当前服 isRealm = false; for(int i = 0; i < noticeObj.notice.Realmlist.Count; i++) { if (noticeObj.notice.Realmlist[i] == playerRealmID) { isRealm = true; break; } } } else if (noticeObj.idInterValue != null) { isRealm = false; // 全服 if (noticeObj.idInterValue.Count == 0) { isRealm = true; } for (int i = 0; i < noticeObj.idInterValue.Count; i++) { int beginRealm = RealmRule(noticeObj.idInterValue[i].Begin); int endRealm = RealmRule(noticeObj.idInterValue[i].End); int tempId = RealmRule(playerRealmID); // 找到该服务器 if (beginRealm <= tempId && tempId <= endRealm) { isRealm = true; break; } } } if (!isRealm) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} not all realm", ID); return failres; } long m_startTime = 0; long m_endTime = 0; //##固定时间触发 if (noticeObj.notice.Triggertype == NoticeTriggerType.FixedTime) { //判断未开始的消息 过期的消息 if (timeSecond <= noticeObj.m_startTime || timeSecond >= noticeObj.m_endTime) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} time not march now={1},start={2},end={3}", ID, timeSecond, noticeObj.m_startTime, noticeObj.m_endTime); return failres; } else { return new Tuple(true, noticeObj.m_startTime, noticeObj.m_endTime); } } //##开服时间触发 //开服时间计算应该不存在时区问题 else if (noticeObj.notice.Triggertype == NoticeTriggerType.OpeningTime) { //根据开服时间计算实际时间 if (curRealm == null) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} curRealm is null", ID); return failres; } //开服时间大于等于 5点 按 当天5点计算开服时间 即 2021-07-10 06:00:00 =》 2021-07-10 05:00:00 //开服时间小于 5点 按 前天5点计算开服时间 即 2021-07-10 04:00:00 =》 2021-07-09 05:00:00 //再去计算偏移 var _openTime = ChatServerUtils.StampToDateTime(curRealm.openTime); if (_openTime.Hour < 5) { _openTime = _openTime.AddDays(-1); } _openTime = new DateTime(_openTime.Year, _openTime.Month, _openTime.Day, 5, 0, 0); ////开始时间相对于开服时间偏移 AddTimes(ref _openTime, noticeObj.notice.Openserverstartday, noticeObj.notice.Openserverendtime.GetString()); m_startTime = ChatServerUtils.GetTimeStamp(_openTime); //结束时间 AddTimes(ref _openTime, noticeObj.notice.Openserverendday, noticeObj.notice.Openserverendtime.GetString()); m_endTime = ChatServerUtils.GetTimeStamp(_openTime); //无间隔天数,不循环 if (noticeObj.Intervaldays == 0) { //判断未开始和结束的消息 if (timeSecond <= m_startTime || timeSecond >= m_endTime) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} no open", ID); return failres; } return new Tuple(true, m_startTime, m_endTime); } //有间隔天数 表示循环 else { //未开始的消息跳过 if (timeSecond < m_startTime) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} no start", ID); return failres; } //已过结束时间 开始算循环 用结束时间往后推 if (timeSecond > m_endTime) { //0 间隔天数 1 持续时长 int timetype = 0; long sTime = 0; while (true) { //间隔天数 if (timetype == 0) { AddTimes(ref m_endTime, noticeObj.Intervaldays, ""); sTime = m_endTime; } //持续时长 else if (timetype == 1) { AddTimes(ref m_endTime, noticeObj.notice.Openserverendday, noticeObj.notice.Openserverendtime.GetString()); } //在本次结束时间之内 if (timeSecond < m_endTime) { break; } else { timetype = timetype == 1 ? 0 : 1; } } //在间隔期内则不展示 if (timetype == 0) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} type is 0", ID); return failres; } else { return new Tuple(true, sTime, m_endTime); } } else { return new Tuple(true, m_startTime, m_endTime); } } } // 定时触发 else { // 小于开始时间 if (timeSecond <= noticeObj.m_startTime || noticeObj.Intervaldays == 0) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} now no start", ID); return failres; } // 从活动开始到现在天数 var duration = (timeSecond - noticeObj.m_startTime) / (24 * 60 * 60); // 活动当天已经过了多少小时 var resHour = ((timeSecond - noticeObj.m_startTime) % (24 * 60 * 60)) / 60 * 60; var resDay = duration % noticeObj.Intervaldays; if (resDay >= noticeObj.notice.Openserverendday) { TraceLog.Trace("SysNoticeSvc.CheckSysNotice ID={0} resDay is long", ID); return failres; } long endtime = noticeObj.m_startTime + (noticeObj.Intervaldays * 24 * 60 * 60); return new Tuple(true, noticeObj.m_startTime, endtime); } } /// /// 添加或更新来自OperationServer的公告推送 /// /// public static void AddOneSysNotice(ref SSSysNotice notice) { List list = ChatServerUtils.GetChatServerData().m_sysNoticeList; //重复的老的先删除,这样支持reload一个配置 foreach (var item in list) { if (item.noticeId == notice.NoticeId) { list.Remove(item); TraceLog.Debug("SysNoticeUtils.AddOneSysNotice id {0} duplicate remove old desc", notice.Id); break; } } //update seq in chat server ChatServerUtils.GetChatServerData().m_sysNoticeSeq = Math.Max(notice.Seq, ChatServerUtils.GetChatServerData().m_sysNoticeSeq); SysNoticeObj obj = new SysNoticeObj(); //obj.m_desc = new SysNoticeDesc().Pase(ref notice); obj.notice = notice; obj.m_seq = notice.Seq; //ChatServerUtils.GetChatServerData().m_sysNoticeSeq; obj.m_startTime = notice.StartTime; obj.sort = notice.Sort; obj.m_endTime = notice.EndTime; obj.m_upTime = notice.Uptime; obj.Intervaldays = notice.Intervaldays; obj.IsShowTimetext = notice.Showtimetext; obj.IsAllSvr = notice.IsAllSvr; obj.giftbagcustoms = notice.Giftbagcustoms; obj.ext = notice.ExtNotice; obj.noticeId = notice.NoticeId; obj.language = notice.Language.GetString(); obj.pageType = notice.PageType; obj.idInterValue = GetRealmPosList(notice.ExtNotice.RealmListStr.GetString()); list.Add(obj); TraceLog.Debug("SysNoticeSvc.AddOneSysNotice seq {0} id {1} language {2} pic {3}" , obj.m_seq, obj.noticeId, obj.language, notice.Title.ToString()); } // private static List GetRealmPosList(string realmlistStr) { //realmlistStr exp:100001-100004#200001-200004#300001,300006#400005 List posList = new List(); try { var realmStrlist = realmlistStr.Split("#"); foreach (var realmlist in realmStrlist) { if (realmlist == "" && realmStrlist.Length != 1) { continue; } if (realmlist.Contains('-')) { var tempList = realmlist.Split("-"); RealmPos tempPos = new RealmPos(); tempPos.Begin = Convert.ToInt32(tempList[0]); tempPos.End = Convert.ToInt32(tempList[1]); posList.Add(tempPos); } else { if (realmlist.Contains(',')) { var realms = realmlist.Split(','); // 排序 List sortRealmList = new List(); foreach (var _RealmID in realms) { int tempId = Convert.ToInt32(_RealmID); sortRealmList.Add(tempId); } sortRealmList.Sort((x, y) => x.CompareTo(y)); if (sortRealmList.Count == 1) { var realmPos = new RealmPos(); realmPos.Begin = sortRealmList[0]; realmPos.End = sortRealmList[0]; posList.Add(realmPos); } else if (sortRealmList.Count == 2) { if (sortRealmList[0] + 1 == sortRealmList[1]) { var realmPos = new RealmPos(); realmPos.Begin = sortRealmList[0]; realmPos.End = sortRealmList[1]; posList.Add(realmPos); } else { var realmPos1 = new RealmPos(); realmPos1.Begin = sortRealmList[0]; realmPos1.End = sortRealmList[0]; posList.Add(realmPos1); var realmPos2 = new RealmPos(); realmPos2.Begin = sortRealmList[1]; realmPos2.End = sortRealmList[1]; posList.Add(realmPos2); } } else { for (int i = 0; i < sortRealmList.Count; i++) { var realmPos = new RealmPos(); realmPos.Begin = sortRealmList[i]; for (int j = i; j < sortRealmList.Count - 1; j++) { //列表连续 if (sortRealmList[j + 1] == sortRealmList[j] + 1) { continue; } else { realmPos.End = sortRealmList[j]; i = j; break; } } if (realmPos.End == 0) { realmPos.End = sortRealmList[i]; } posList.Add(realmPos); } } } else { if (realmlist != "" && realmlist != null) { int RealmID = Convert.ToInt32(realmlist); if (RealmID != 0) { var realmPos = new RealmPos(); realmPos.Begin = RealmID; realmPos.End = RealmID; posList.Add(realmPos); } } } } } } catch (Exception ex) { TraceLog.Error("MailSendWithRule.ParseRealm error:{0}", ex.Message); return posList; } return posList; } // private static void AddOneSysNotice(long startTime, long endTime, SysNoticeDesc desc) // { // // List list = ChatServerUtils.GetChatServerData().m_sysNoticeList; // // //重复的老的先删除,这样支持reload一个配置 // foreach (var item in list) // { // if (item.m_desc.id == desc.id) // { // list.Remove(item); // // TraceLog.Debug("SysNoticeUtils.AddOneSysNotice id {0} duplicate remove old desc", desc.id); // // break; // } // } // // // ChatServerUtils.GetChatServerData().m_sysNoticeSeq++; // // SysNoticeObj obj = new SysNoticeObj(); // obj.m_desc = desc; // obj.m_seq = ChatServerUtils.GetChatServerData().m_sysNoticeSeq; // obj.m_startTime = startTime; // obj.m_endTime = endTime; // obj.language = desc.language.ToLower(); // obj.pageType = desc.pageType; // list.Add(obj); // // TraceLog.Debug("SysNoticeUtils. seq {0} id {1} content {2}" // , obj.m_seq, obj.m_desc.id, obj.m_desc.content); // } // private static void RemoveOneSysNoticeByID(uint id) // { // List list = ChatServerUtils.GetChatServerData().m_sysNoticeList; // // //重复的老的先删除,这样支持reload一个配置 // foreach (var item in list) // { // if (item.m_desc.id == id) // { // list.Remove(item); // TraceLog.Debug("SysNoticeUtils.RemoveOneSysNoticeByID id {0} duplicate remove old desc", id); // //ChatServerUtils.GetChatServerData().m_sysNoticeSeq++; // break; // } // } // } /// /// 时长转秒数 /// /// /// /// /// /// /// private static void AddTimes(ref long date, int day, string time) { var dateobj = ChatServerUtils.StampToDateTime(date); AddTimes(ref dateobj, day, time); date = ChatServerUtils.GetTimeStamp(dateobj); } private static void AddTimes(ref DateTime date, int day, string time) { int hour; int minute; int second; var times = time.Split(':'); if (day != 0) { date = date.AddDays(day); } if (times.Length == 3) { hour = int.Parse(times[0]); if (hour != 0) { date = date.AddHours(hour); } minute = int.Parse(times[1]); if (minute != 0) { date = date.AddMinutes(minute); } second = int.Parse(times[2]); if (second != 0) { date = date.AddSeconds(second); } } } /// /// type(公告类型): 0 - all, 1 - popUp, 2 - click /// /// /// /// /// /// public static void FillSysNotices(ref CSQuerySysNoticeRes res, PlayerOnChat player, int seq, string language, int type=0) { res.LastSeq = ChatServerUtils.GetChatServerData().m_sysNoticeSeq; if (seq >= ChatServerUtils.GetChatServerData().m_sysNoticeSeq) { return; } var _ServerData = ChatServerUtils.GetChatServerData(); ///公告列表 List list = _ServerData.m_sysNoticeList; //公告这里需要排序 暂时倒序sort foreach (SysNoticeObj noticeObj in list.OrderByDescending(s => s.sort)) { var Checkres = CheckSysNotice(noticeObj.notice.Id, player.RealmID); if (!Checkres.Item1) { TraceLog.Trace("SysNoticeSvc.FillSysNotices id={0}, noticeId={1} ,check result false", noticeObj.notice.Id, noticeObj.noticeId); continue; } if (language.ToLower() != noticeObj.language.ToLower()) { TraceLog.Trace("SysNoticeSvc.FillSysNotices id={0}, noticeId={1} ,language not march",noticeObj.notice.Id, noticeObj.noticeId); continue; } var notice = new CSSysNotice(); notice.Seq = noticeObj.m_seq; if (noticeObj.notice.Triggertype == 0) { notice.StartTime = noticeObj.m_startTime; notice.EndTime = noticeObj.m_endTime; } else { notice.StartTime = Checkres.Item2; notice.EndTime = Checkres.Item3; } notice.Title.SetString(player.GetPlayerLanguageStr(noticeObj.notice.Title.GetString())); notice.Content.SetString(player.GetPlayerLanguageStr(noticeObj.notice.Content.GetString())); notice.Icon.SetString(noticeObj.notice.Icon.GetString()); notice.Pic.SetString(noticeObj.notice.Pic.GetString()); notice.Jump = noticeObj.notice.Jump; // notice.Popup = noticeObj.m_desc.popUp; notice.Id = (int)noticeObj.notice.Id; notice.Link.SetString(noticeObj.notice.Link.GetString()); notice.Dungeonid = noticeObj.notice.Dungeonid; notice.Sort = noticeObj.sort; notice.IsShow = noticeObj.notice.State == 1; notice.Showtimetext = noticeObj.IsShowTimetext; notice.IsAllSvr = noticeObj.IsAllSvr; notice.Giftbagcustoms = noticeObj.giftbagcustoms; notice.JumpParam = noticeObj.notice.JumpParam; notice.PageType = noticeObj.pageType; if (notice.PageType == 0) { notice.PageType = noticeObj.notice.PageType; } //扩展字段 if (noticeObj.ext.Havedata) { notice.Type = noticeObj.ext.Type; notice.TextParams = noticeObj.ext.TextParams; } if (noticeObj.notice.Popup == 1) { if(type == 2) { TraceLog.Trace("SysNoticeSvc.FillSysNotices id={0}, noticeId={1} ,type={2} not march",noticeObj.notice.Id, noticeObj.noticeId,type); continue; } if (res.PopupList.Count < res.PopupList.GetMaxCount()) { res.PopupList.Add(notice); } else { TraceLog.Error("SysNoticeSvc.FillSysNotices CSSysNotice.List over MaxCount"); } } else { if (type == 1) { TraceLog.Trace("SysNoticeSvc.FillSysNotices id={0}, noticeId={1} ,type={2} not march",noticeObj.noticeId, noticeObj.noticeId,type); continue; } if (res.ClickList.Count < res.ClickList.GetMaxCount()) { res.ClickList.Add(notice); } else { TraceLog.Error("SysNoticeSvc.FillSysNotices CSSysNotice.List over MaxCount"); } } } } private static int RealmRule(int realmId) { string realmStr = realmId.ToString(); if (realmStr.Length < 6) return realmId; string area = realmStr.Substring(0, 1); string reaml = realmStr.Substring(3); Int32.TryParse(area + reaml, out int result); return result; } public override int GetServiceType() { return ChatServiceType.SysNotice; } public override void Dispose() { ChatServerUtils.GetChatServerData().m_sysNoticeList.Clear(); } } }