using System.Collections.Concurrent; using System.Net; using GameServer.Contents.Battle.Doc; using MetaAssets; using Newtonsoft.Json; using ServerBase; using ServerCommon; using ServerCore; namespace GameServer; public class BattleEventCheckTicker : EntityTicker { public BattleEventCheckTicker(double onTickIntervalMilliseconds, CancellationTokenSource? cts) : base(EntityType.BattleEventCheckTicker, onTickIntervalMilliseconds, cts) { } public override async Task onTaskTick() { var result = await refreshEvent(); if (result.isFail()) { Log.getLogger().error($"BattleEventCheckTicker onTaskTick error :{result.toBasicString()}"); } } public override async Task onInit() { await refreshEvent(); var result = new Result(); return result; } public async Task refreshEvent() { var result = new Result(); (result, var docs) = await loadFromDB(); if (result.isFail()) return result; if (docs.Count == 0) { Log.getLogger().info("Not exist Battle Evnet From DB"); return result; } //실제로 작동하는 battle event로 만들기 await updateBattleEvent(docs); return result; } private async Task<(Result, List)> loadFromDB() { var server_logic = GameServerApp.getServerLogic(); var dynamo_db_client = server_logic.getDynamoDbClient(); var doc = new BattleEventDoc(); var query_config = dynamo_db_client.makeQueryConfigForReadByPKOnly(doc.getPK()); (var result, var read_doc_list) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig(query_config); if (result.isFail()) { return (result, new()); } Log.getLogger().info($"load battle event from db eventdoc count : {read_doc_list.Count}"); return (result, read_doc_list); } public List loadTempEvent() { List battle_event_attribs = new(); for(int i = 1; i < 15; i++) { var battle_event_attrib = new BattleEventAttrib(); battle_event_attrib.m_event_id = i; battle_event_attrib.m_is_active = i == 11 ? false : true; battle_event_attrib.m_start_day = DateTimeHelper.Current.Date; battle_event_attrib.m_start_hour = i-1; //9시 부터 셋팅 battle_event_attrib.m_start_min = 00; battle_event_attrib.m_instance_id = 1017006 + ((i % 3) % 2); battle_event_attrib.m_period = OncePeriodRangeType.Daily; battle_event_attrib.m_day_of_week_type = new(); battle_event_attrib.m_ffa_config_data_id = 1; battle_event_attrib.m_ffa_reward_group_id = 1; battle_event_attrib.m_ffa_hot_time = 1 + (i % 3) ; battle_event_attrib.m_round_count = 1 + (i % 5); battle_event_attrib.m_end_date = DateTimeHelper.Current.Date.AddDays(7); battle_event_attribs.Add(battle_event_attrib); } return battle_event_attribs; } public async Task updateBattleEvent(List docs) { await Task.CompletedTask; DateTime now = DateTimeHelper.Current; DateTime today = now.Date; deleteOldEvents(now); foreach (var read_doc in docs) { addNewEvent(read_doc, today, now); } foreach (var read_doc in docs) { checkModifiedEvent(now, read_doc); } BattleInstanceManager.It.logSystemBattleEvents(); } private void addNewEvent(BattleEventDoc doc, DateTime today, DateTime now) { var attrib = doc.getAttrib(); if (attrib is null) { Log.getLogger().error("BattleEventDoc BattleEventAttrib is null !!!!"); return; } //메모리에 존재하는 이벤트면 리턴 if (BattleInstanceManager.It.existSystemBattleEvent(attrib.m_event_id)) return; //아직 시작 안한 이벤트면 리턴 var start_day = DateTime.SpecifyKind(attrib.m_start_day, DateTimeKind.Utc); var recently_events = CreateSystemBattleEvents(attrib, start_day, now); foreach (var new_ev in recently_events) { BattleInstanceManager.It.addNewSystemBattleEvent(new_ev, true); } var new_events = CreateSystemBattleEvents(attrib, today, now); foreach (var new_ev in new_events) { BattleInstanceManager.It.addNewSystemBattleEvent(new_ev, true); } //다음날 events 도 추가능한것은 추가한다. var tomorrow_new_events = CreateSystemBattleEvents(attrib, today.AddDays(1), now); foreach (var new_ev in tomorrow_new_events) { BattleInstanceManager.It.addNewSystemBattleEvent(new_ev, false); } } private void checkModifiedEvent(DateTime now, BattleEventDoc doc) { var events = BattleInstanceManager.It.getSystemBattleEvents(); var attrib = doc.getAttrib(); if (attrib is null) { Log.getLogger().error("BattleEventDoc BattleEventAttrib is null !!!!"); return; } if (false == events.TryGetValue(attrib.m_event_id, out var event_data)) return; if (event_data.m_start_time <= now) return; var delete_event_ids = new List(); if (attrib.m_is_active == false) { delete_event_ids.Add(attrib.m_event_id); } if (delete_event_ids.Count > 0) { Log.getLogger().info($"deleted event ids : {JsonConvert.SerializeObject(delete_event_ids)}"); BattleInstanceManager.It.removeSystemBattleEvents(delete_event_ids); } } private void deleteOldEvents(DateTime now) { var events = BattleInstanceManager.It.getSystemBattleEvents(); //오래된 이벤트 id 취합 및 삭제 List deleted_event_ids = new(); foreach (var battle_events in events.Values.ToList()) { var event_id = battle_events.m_event_id; var start_time = battle_events.m_start_time; var destroyed_time = BattleRoomHelper.calculateDestroyedTime(start_time, battle_events.m_ffa_config_data_id, battle_events.m_round_count); if (destroyed_time < now) { deleted_event_ids.Add(event_id); } } if (deleted_event_ids.Count > 0) { Log.getLogger().info($"deleted event ids : {JsonConvert.SerializeObject(deleted_event_ids)}"); BattleInstanceManager.It.removeSystemBattleEvents(deleted_event_ids); } } private List CreateSystemBattleEvents(BattleEventAttrib attrib, DateTime startDay, DateTime now) { List new_events = new(); if (BattleInstanceManager.It.existSystemBattleEvent(attrib.m_event_id)) return new_events; var start_time = makeSystemBattleEventStartTime(attrib, startDay); //파괴되는 시간을 계산했는데 이벤트 종료시간보다 크면 안넣는다. var joinableTime_time = BattleRoomHelper.calculateRoomJoinableTime(start_time, attrib.m_ffa_config_data_id, attrib.m_round_count); if (joinableTime_time < now) return new_events; if (attrib.m_end_date < joinableTime_time) return new_events; //이벤트 비활성 상태면 안넣는다. if (attrib.m_is_active == false) return new_events; switch (attrib.m_period) { case OncePeriodRangeType.NONE: case OncePeriodRangeType.Daily: new_events.AddRange(makeDailySystemBattleEvent(start_time, now, attrib)); break; case OncePeriodRangeType.Weekly: new_events.AddRange(makeWeekliySystemBattleEvent(startDay, now, attrib)); break; case OncePeriodRangeType.Monthly: new_events.AddRange(makeMonthiySystemBattleEvent(startDay, now, attrib)); break; case OncePeriodRangeType.Nolimit: Log.getLogger($"There is not used Type in Battle System Event !!!! eventId : {attrib.m_event_id}"); break; } if (new_events.Count > 0) { string new_events_str = JsonConvert.SerializeObject(new_events); Log.getLogger().info($"new battele events set {new_events_str}"); } return new_events; } private DateTime makeSystemBattleEventStartTime(BattleEventAttrib attrib, DateTime today) { switch (attrib.m_period) { case OncePeriodRangeType.NONE: var start_day = DateTime.SpecifyKind(attrib.m_start_day, DateTimeKind.Utc); return start_day.AddHours(attrib.m_start_hour).AddMinutes(attrib.m_start_min); case OncePeriodRangeType.Daily: case OncePeriodRangeType.Weekly: case OncePeriodRangeType.Monthly: return today.AddHours(attrib.m_start_hour).AddMinutes(attrib.m_start_min); case OncePeriodRangeType.Nolimit: Log.getLogger($"There is not used Type in Battle System Event !!!! eventId : {JsonConvert.SerializeObject(attrib)}"); return DateTimeHelper.MinTime; } return DateTimeHelper.MinTime; } // private List makeNoneTypeSystemBattleEvent(DateTime startTime, DateTime now, BattleEventAttrib attrib) // { // List events = new(); // // if (startTime >= now) // && startTime < now.AddDays(1)) // { // if (attrib.m_end_date <= now) return events; // // SystemBattleEvent new_event = new SystemBattleEvent // { // m_event_id = attrib.m_event_id, // m_instance_id = attrib.m_instance_id, // m_start_time = startTime, // m_ffa_config_data_id = attrib.m_ffa_config_data_id, // m_ffa_reward_group_id = attrib.m_ffa_reward_group_id, // m_ready_time = startTime.AddMinutes(-5), // m_is_send_noti = false, // m_ffa_hot_time = attrib.m_ffa_hot_time, // m_round_count = attrib.m_round_count // }; // events.Add(new_event); // } // return events; // } private List makeDailySystemBattleEvent(DateTime startTime, DateTime now, BattleEventAttrib attrib) { List events = new(); if (attrib.m_end_date <= now) return events; SystemBattleEvent new_event = new SystemBattleEvent { m_event_id = attrib.m_event_id, m_instance_id = attrib.m_instance_id, m_start_time = startTime, m_ffa_config_data_id = attrib.m_ffa_config_data_id, m_ffa_reward_group_id = attrib.m_ffa_reward_group_id, m_ready_time = startTime.AddMinutes(-5), m_is_send_noti = false, m_ffa_hot_time = attrib.m_ffa_hot_time, m_round_count = attrib.m_round_count }; events.Add(new_event); return events; } private List makeWeekliySystemBattleEvent(DateTime today, DateTime now, BattleEventAttrib attrib) { List events = new(); foreach (var dayOfWeek in attrib.m_day_of_week_type) { int daysUntilNext = ((int)dayOfWeek - (int)today.DayOfWeek + 7) % 7; DateTime eventTime = today.AddDays(daysUntilNext).Date .AddHours(attrib.m_start_hour) .AddMinutes(attrib.m_start_min); if (eventTime >= now)// && eventTime < now.AddDays(1)) { if (attrib.m_end_date <= now) return events; events.Add(new SystemBattleEvent { m_event_id = attrib.m_event_id, m_instance_id = attrib.m_instance_id, m_start_time = eventTime, m_ffa_config_data_id = attrib.m_ffa_config_data_id, m_ffa_reward_group_id = attrib.m_ffa_reward_group_id, m_ready_time = eventTime.AddMinutes(-5), m_is_send_noti = false, m_ffa_hot_time = attrib.m_ffa_hot_time, m_round_count = attrib.m_round_count }); } } return events; } private List makeMonthiySystemBattleEvent(DateTime today, DateTime now, BattleEventAttrib attrib) { List events = new(); DateTime monthlyTime = new DateTime( today.Year, today.Month, attrib.m_start_day.Day, attrib.m_start_hour, attrib.m_start_min, 0 ); if (monthlyTime >= now)// && monthlyTime < now.AddDays(1)) { if (attrib.m_end_date <= now) return events; events.Add(new SystemBattleEvent { m_event_id = attrib.m_event_id, m_instance_id = attrib.m_instance_id, m_start_time = monthlyTime, m_ffa_config_data_id = attrib.m_ffa_config_data_id, m_ffa_reward_group_id = attrib.m_ffa_reward_group_id, m_ready_time = monthlyTime.AddMinutes(-5), m_is_send_noti = false, m_ffa_hot_time = attrib.m_ffa_hot_time, m_round_count = attrib.m_round_count }); } return events; } }