초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,501 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using NeoSmart.AsyncLock;
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 BattleInstanceManager : Singleton<BattleInstanceManager>
{
private AsyncLock m_lock_init = new();
public AsyncLock m_lock_data_load = new();
private ConcurrentDictionary<string, BattleInstanceRoom> m_battle_instances = new(); //인스턴스 생성 삭제를 주로 관리 하기 위한 Dictionary ... 아...이거 구조 별론데,....
private ConcurrentDictionary<Int32 /*event_id*/, SystemBattleEvent> m_battle_events = new();
public async Task onInit()
{
//1. 이벤트 관리하는 Task 추가
var result = await createBattleEventCheckerTask();
}
public bool hasBattleInstance(string roomId)
{
return m_battle_instances.ContainsKey(roomId);
}
public BattleInstanceRoom? getBattleInstanceRoom(string roomId)
{
if (false == m_battle_instances.TryGetValue(roomId, out var room))
{
return null;
}
return room;
}
public ConcurrentDictionary<string, BattleInstanceRoom> getBattleInstanceRooms()
{
return m_battle_instances;
}
//
// public bool isLoadComplete(string roomId)
// {
// if (false == m_battle_instances.TryGetValue(roomId, out var battleInstanceRoom))
// {
// return false;
// }
// return battleInstanceRoom.m_is_load_complete;
// }
public async Task<Result> battleInstanceInit(InstanceRoom instanceRoom, string roomId)
{
var result = new Result();
var err_msg = string.Empty;
using (await m_lock_init.LockAsync())
{
//1. 배틀 인스턴스에 대한 정보 생성
Log.getLogger().info($"Battle Instance Create And Init : {roomId}");
if (hasBattleInstance(roomId)) return result;
// instance 정보 추가 등록
var server_logic = GameServerApp.getServerLogic();
var instance_room_storage = new InstanceRoomStorage();
instance_room_storage.Init(server_logic.getRedisDb(), "");
DateTime start_time = DateTimeHelper.Current;
Int32 config_id = 1;
Int32 reward_id = 1;
Int32 hot_time = 1;
Int32 round_count = 8;
var system_battle_event = BattleRoomHelper.getBattleRoomStartTimeByEventId(roomId);
if (system_battle_event is null)
{
Log.getLogger().error($"system_battle_event is null!!! : {result.toBasicString()} - instanceRoomId:{roomId}");
}
else
{
start_time = system_battle_event.m_start_time;
config_id = system_battle_event.m_ffa_config_data_id;
reward_id = system_battle_event.m_ffa_reward_group_id;
hot_time = system_battle_event.m_ffa_hot_time;
round_count = system_battle_event.m_round_count;
}
result = await instance_room_storage.setInstanceRoomExtraInfo(roomId, EPlaceType.BattleRoom, start_time);
if (result.isFail())
{
Log.getLogger().error($"Failed to BattleRoom setInstanceRoomExtraInfo() !!! : {result.toBasicString()} - instanceRoomId:{roomId}");
return result;
}
BattleInstanceRoom battle_instance_room = new BattleInstanceRoom(instanceRoom, start_time, config_id, reward_id, hot_time, round_count);
if (false == m_battle_instances.TryAdd(roomId, battle_instance_room))
{
//이미 존재하는 경우는 onInit 절차를 거쳤다고 생각하고, init 처리 안해주고 리턴
err_msg = $"Battle Instance Room Already exist room_id : {roomId}";
result.setFail(ServerErrorCode.BattleInstanceInfoAlreadyExist, err_msg);
Log.getLogger().warn(result.toBasicString());
return result;
}
//2. 초기화
result = await battle_instance_room.init();
if (result.isFail())
{
Log.getLogger().warn(result.toBasicString());
return result;
}
}
Log.getLogger().info($"battleInstanceInit done roomId : {roomId}");
return result;
}
public Result addOrUpatePlayer(string roomId, Player player)
{
var result = new Result();
string err_msg = string.Empty;
if (false == m_battle_instances.TryGetValue(roomId, out var battle_instance_room))
{
err_msg = $"m_battle_instances not exist battleRoomInstance, roomId : {roomId}";
result.setFail(ServerErrorCode.BattleInstanceInfoNotExist, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
//유저 정보 추가 해줘야 한다.
result = battle_instance_room.AddOrUpdatePlayer(player);
return result;
}
private async Task<Result> createBattleEventCheckerTask()
{
var result = new Result();
var battle_entity_ticker_initializers = new Initializers();
//채널 인던 다 필요한가?
//이벤트 인스턴스 관련 생성 삭제에 대한 관리 Ticker
//battle_entity_ticker_initializers.appendInitializer(new BattleEventCheckTicker(1000, null));
//battle_entity_ticker_initializers.appendInitializer(new BattleEventNotifyTicker(ServerCommon.Constant.EVENT_UPDATE_INTERVAL_MMIN, null));
result = await battle_entity_ticker_initializers.init("BattleEntityTickers");
if (result.isFail())
{
Log.getLogger().error($"Failed to init() !!! : {result.toBasicString()}");
return result;
}
var battle_event_check_ticker = new BattleEventCheckTicker(BattleConstant.BATTLE_EVENT_CHECK_INTERVAL, null);
await battle_event_check_ticker.onInit();
await createTask(battle_event_check_ticker);
var battle_event_notify_ticker = new BattleEventNotifyTicker(ServerCommon.Constant.EVENT_UPDATE_INTERVAL_MMIN, null);
await battle_event_check_ticker.onInit();
await createTask(battle_event_notify_ticker);
return result;
}
private async Task<Result> createTask(EntityTicker ticker)
{
var result = new Result();
await Task.CompletedTask;
try
{
new PeriodicTaskTimer( ticker.getTypeName() , ticker.getOnTickIntervalMilliseconds(), ticker.getCancelToken(), ticker.onTaskTick);
Log.getLogger().debug("createTask done");
}
catch(Exception e)
{
var err_msg = $"Exception !!!, new PeriodicTaskTimer() : exception:{e}";
result.setFail(ServerErrorCode.TryCatchException, err_msg);
return result;
}
return result;
}
public async Task tryLeaveBattelInstance(Player player, string instanceRoomId)
{
if (false == BattleRoomHelper.checkBattleActive()) return;
Log.getLogger().debug($"tryLeaveBattelInstance start instanceRoomId : {instanceRoomId}");
var location_attribute = player.getEntityAttribute<LocationAttribute>();
NullReferenceCheckHelper.throwIfNull(location_attribute, () => $"location attribute is null !!! - {player.toBasicString()}");
//var instanceRoomId = location_attribute.CurrentIndunLocation.InstanceRoomId;
if (instanceRoomId == string.Empty)
{
Log.getLogger().warn($"tryLeaveBattelInstance IntanceRoomId is Empty");
removeBattlePlayer(player.getUserGuid());
return;
}
if (false == m_battle_instances.TryGetValue(instanceRoomId, out var battleInstanceRoom))
{
removeBattlePlayer(player.getUserGuid());
return;
}
await battleInstanceRoom.removePodCombat(player);
var host_user_guid = battleInstanceRoom.m_host_migrator.getHostUserGuid();
if (player.getUserGuid().Equals(host_user_guid))
{
using (var releaser = await battleInstanceRoom.getAsyncLock())
{
battleInstanceRoom.m_host_migrator.removeHost();
}
}
//여기서 instanceroom 이 is Destroy 면 DestroyBattleRoom 호출 해줄것
if (battleInstanceRoom.m_instance_room.isDestroy)
{
m_battle_instances.TryRemove(instanceRoomId, out var _);
await battleInstanceRoom.destroyBattleRoom();
Log.getLogger().debug($"tryLeaveBattelInstance destroy battle room instanceRoomId : {instanceRoomId}");
}
}
public async Task tryDestroyBattleRoom(string instanceRoomId)
{
if (false == BattleRoomHelper.checkBattleActive()) return;
if (false == instanceRoomId.Contains(BattleConstant.PREFIX_BATTLE_INSTANCE_ROOM_ID)) return;
if (false == m_battle_instances.TryGetValue(instanceRoomId, out var battleInstanceRoom))
{
Log.getLogger().error($"instanceRoomId : {instanceRoomId} is not exist instnaces");
return;
}
var is_destroy = battleInstanceRoom.m_instance_room.isDestroy;
if (is_destroy)
{
await battleInstanceRoom.destroyBattleRoom();
m_battle_instances.TryRemove(instanceRoomId, out _);
}
}
private void removeBattlePlayer(string userGuid)
{
foreach (var battle_instance_room in m_battle_instances.Values)
{
battle_instance_room.removeBattlePlayerIfExist(userGuid);
}
}
public async Task<bool> LeaveBattleRoom(Player player, string instanceRoomId, bool disconnected = false)
{
if (false == m_battle_instances.TryGetValue(instanceRoomId, out var battleRoom))
{
Log.getLogger().info($"LeaveBattleRoom m_battle_instances.TryGetValue false instanceRoomId : {instanceRoomId}");
return false;
}
await battleRoom.LeaveBattleRoom(player, instanceRoomId, disconnected);
// if (battleRoom.m_instance_room.isDestroy)
// {
// InstanceRoomManager.Instance.DestroyRoom(instanceRoomId);
// }
Log.getLogger().debug($"leave battle room player : {player.toBasicString()}, instanceRoomId : {instanceRoomId}");
return true;
}
public async Task<Result> sendNtfAboutBattleInstance(BattleInstanceRoom battieInstanceRoom, Player player)
{
var result = new Result();
BattleRoomNotifyHelper.send_GS2C_NTF_BATTLE_INSTANCE_STATE(battieInstanceRoom, player);
BattleRoomNotifyHelper.send_GS2C_NTF_POD_COMBAT_STATE(battieInstanceRoom, player);
sendNtfBattleObjectsState(battieInstanceRoom, player);
var host_user_guid = battieInstanceRoom.m_host_migrator.getHostUserGuid();
if (!host_user_guid.Equals(string.Empty))
{
BattleRoomNotifyHelper.send_GS2C_NTF_P2P_HOST_UPDATE(player, host_user_guid);
}
await Task.CompletedTask;
return result;
}
private void sendNtfBattleObjectsState(BattleInstanceRoom battleInstanceRoom, Player player)
{
List<BattleObjectInfo> infos = new();
var attribute = battleInstanceRoom.getEntityAttribute<BattleInstanceSnapshotAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"attribute is null !!!");
var now = DateTimeHelper.Current;
foreach (var weapon in attribute.m_combat_pod_mode.m_weapons.Values)
{
BattleObjectInfo info = new();
info.AnchorGuid = weapon.m_anchor_guid;
info.IsActive = weapon.m_active_time <= now ? BoolType.True : BoolType.False;
infos.Add(info);
}
foreach (var buff in attribute.m_combat_pod_mode.m_buffs.Values)
{
BattleObjectInfo info = new();
info.AnchorGuid = buff.m_anchor_guid;
info.IsActive = buff.m_active_time <= now ? BoolType.True : BoolType.False;
infos.Add(info);
}
foreach (BattleObjectPodStorage storage in attribute.m_combat_pod_mode.m_pod_storages.Values)
{
//storage.m_is_active = true;
BattleObjectInfo info = new();
info.AnchorGuid = storage.m_anchor_guid;
info.IsActive = storage.m_is_active ? BoolType.True : BoolType.False;
infos.Add(info);
}
foreach (BattleObjectPickupPod pickup in attribute.m_combat_pod_mode.m_pickup_pods.Values)
{
BattleObjectInfo info = new();
info.AnchorGuid = pickup.m_anchor_guid;
info.IsActive = pickup.m_is_active ? BoolType.True : BoolType.False;
infos.Add(info);
Log.getLogger().info($"pickup pod info anchor_guid : {info.AnchorGuid}, is Active : {info.IsActive}");
}
BattleRoomNotifyHelper.send_GS2C_NTF_BATTLE_OBJECT_STATE_INFO(infos, player);
}
public bool isBattleInstance(Player player)
{
var location_action = player.getEntityAction<LocationAction>();
NullReferenceCheckHelper.throwIfNull(location_action, () => $"location_action is null !!! - {player.toBasicString()}");
var current_indun_location = location_action.getCurrentLocation() as IndunLocation;
NullReferenceCheckHelper.throwIfNull(current_indun_location, () => $"current_indun_location is null !!! - {player.toBasicString()}");
var instance_room_Id = current_indun_location.InstanceRoomId;
if (instance_room_Id == string.Empty) return false;
Log.getLogger().debug($"is Battle Instance check : instance room id : {instance_room_Id}");
if (instance_room_Id.Contains("battle_instance"))
{
return true;
}
return false;
//result.setFail(ServerErrorCode.BattleInstnaceNotUsedPacket, "");
}
public List<BattleEventInfo> getAllProtoBattleEvents()
{
List<BattleEventInfo> infos = new();
foreach(var system_battle_event in m_battle_events.Values.ToList())
{
BattleEventInfo battle_event_info = new();
battle_event_info.EventId = system_battle_event.m_event_id;
battle_event_info.InstanceId = system_battle_event.m_instance_id;
battle_event_info.StartTime = Timestamp.FromDateTime(system_battle_event.m_start_time);
battle_event_info.ConfigDataId = system_battle_event.m_ffa_config_data_id;
battle_event_info.RewardGroupId = system_battle_event.m_ffa_reward_group_id;
battle_event_info.HotTime = system_battle_event.m_ffa_hot_time;
battle_event_info.RoundCount = system_battle_event.m_round_count;
infos.Add(battle_event_info);
}
return infos;
}
public BattleEventInfo makeProtoBattleEvent(SystemBattleEvent battleEvent)
{
BattleEventInfo battle_event_info = new();
battle_event_info.EventId = battleEvent.m_event_id;
battle_event_info.InstanceId = battleEvent.m_instance_id;
battle_event_info.StartTime = Timestamp.FromDateTime(battleEvent.m_start_time);
battle_event_info.ConfigDataId = battleEvent.m_ffa_config_data_id;
battle_event_info.RewardGroupId = battleEvent.m_ffa_reward_group_id;
battle_event_info.HotTime = battleEvent.m_ffa_hot_time;
battle_event_info.RoundCount = battleEvent.m_round_count;
return battle_event_info;
}
// public async Task setBattleEventAttribs(List<BattleEventAttrib> battleEventAttribs)
// {
// using (await m_lock_data_load.LockAsync())
// {
// m_battle_event_attribs.Clear();
// m_battle_event_attribs = battleEventAttribs;
// }
//
// }
// public async Task<List<BattleEventAttrib>> copyBattleEventAttribs()
// {
// List<BattleEventAttrib> attribs = new();
// using (await m_lock_data_load.LockAsync())
// {
// foreach (var attrib in m_battle_event_attribs)
// {
// attribs.Add(attrib.clone());
// }
// }
//
// return attribs;
// }
public ConcurrentDictionary<Int32 /*event_id*/, SystemBattleEvent> getSystemBattleEvents()
{
return m_battle_events;
}
public bool getSystemBattleEvent(Int32 eventId, [MaybeNullWhen(false)]out SystemBattleEvent battleEvent)
{
if (false == m_battle_events.TryGetValue(eventId, out battleEvent))
{
Log.getLogger($"Not exsist Battle event !!! eventId : {eventId}");
return false;
}
return true;
}
public void removeSystemBattleEvents(List<Int32> events)
{
foreach (var event_id in events)
{
if (false == m_battle_events.TryRemove(event_id, out var ev))
{
Log.getLogger().warn($"remove battle event fali event_id : {event_id}");
}
}
}
public bool existSystemBattleEvent(Int32 eventId)
{
return m_battle_events.ContainsKey(eventId);
}
public void logSystemBattleEvents()
{
Log.getLogger().info($"updated system battle events : {JsonConvert.SerializeObject(m_battle_events)}");
}
public void setSystemBattleEvents(ConcurrentDictionary<Int32 /*event_id*/, SystemBattleEvent> newEvents)
{
m_battle_events = newEvents;
}
public bool addNewSystemBattleEvent(SystemBattleEvent ev, bool needErrroLog)
{
if (false == m_battle_events.TryAdd(ev.m_event_id, ev))
{
if (needErrroLog)
{
Log.getLogger().error($"System battle Event try Add Fail, eventId : {ev.m_event_id}, events : {JsonConvert.SerializeObject(m_battle_events)}");
}
return false;
}
return true;
}
public BattleInstanceManager Self => this;
}