초기커밋

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,474 @@
using System.Collections.Concurrent;
using Axion.Collections.Concurrent;
using Newtonsoft.Json;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace GameServer;
public class BattleInstanceRoom : EntityBase, IWithLogActor
{
//public string m_instance_room_guid { get; } = string.Empty;
public bool m_is_load_complete { get; private set; } = false;
public InstanceRoom m_instance_room { get; }
private readonly CancellationTokenSource m_cancel_token = new();
public readonly IHostMigrator m_host_migrator; //생성자에서 모드에 맞춰서 할당한다.
public BattlePlayMode m_play_mode { get; set; } = BattlePlayMode.PodCombat;
public DateTime m_battle_instance_event_start_time { get; private set; } = DateTimeHelper.Current; //실제 이벤트 시작시간
//public DateTime m_battle_instance_load_time { get; } = DateTimeHelper.Current; //이벤트 시작시간과 관계 없이 메모리에 로드 될때의 시간 이 변수가 필요할지 모르겠다.
//todo : 모드별 관리 메타를 따로 구성해야할듯...
//todo : 제네릭으로 받아도 되려나?.. 고민 필요 우선 임시데이터
public Int32 m_pod_combat_reward_group_id = 1;
public Int32 m_pod_combat_ffa_id = 1;
public BattleFFAConfigData m_ffa_config_meta;
public Dictionary<int, BattleFFARewardData> m_ffa_reward_meta = new();
public Int32 m_hot_time_reward = 1;
public Int32 m_round_count = 8;
//public Int32 m_pickup_pod_reward_max_count { get; } = 2;
//public int m_max_step_per_round { get; set; } = 10;
public ConcurrentHashSet<string /*anchor_guid*/> m_respawn_pos_anchors_meta { get; private set; } = new(); //이건 랜덤 돌릴 일이 잦아서 그냥 들고 있는다...
public ConcurrentDictionary<int /*battle_group_id*/ , HashSet<string>> m_battle_pod_storage_guid_group { get; private set; } = new(); //pod combat을 생성해줄때 필요
public ConcurrentDictionary<int /*battle_group_id*/ , HashSet<string>> m_battle_pickup_pod_guid_group { get; private set; } = new();
public BattleInstanceRoom(InstanceRoom room, DateTime eventStartTime, Int32 configId, Int32 rewardId, Int32 hotTime, Int32 roundCount)
: base(EntityType.BattleInstance)
{
m_instance_room = room;
NullReferenceCheckHelper.throwIfNull(m_instance_room, () => $"m_instance_room is null !!!");
m_battle_instance_event_start_time = eventStartTime;
m_play_mode = BattlePlayMode.PodCombat;
m_host_migrator = BattleRoomHelper.createHostMigrator(m_play_mode);
m_pod_combat_ffa_id = configId;
m_pod_combat_reward_group_id = rewardId;
m_hot_time_reward = hotTime;
m_round_count = roundCount;
//m_instance_room_guid = BattleConstant.PREFIX_BATTLE_TRANSACTION_GUID + System.Guid.NewGuid();
// BattleFFAConfigData
if (false == MetaData.Instance._BattleFFAConfigMetaTable.TryGetValue(m_pod_combat_ffa_id, out var configData))
{
var err_msg = $"Not exist Battle Conig Data id : {m_pod_combat_ffa_id}";
Log.getLogger().error(err_msg);
NullReferenceCheckHelper.throwIfNull(configData, () => $"configData is null !!!");
}
m_ffa_config_meta = new BattleFFAConfigData(new BattleFFAConfigDataMutable()
{
Id = configData.Id,
Description = configData.Description,
PlayerRespawnTime = configData.PlayerRespawnTime,
DefaultRoundCount = configData.DefaultRoundCount,
RoundTime = configData.RoundTime,
NextRoundWaitTime = configData.NextRoundWaitTime,
ResultUIWaitTime = configData.ResultUIWaitTime,
GetRewardTime = configData.GetRewardTime,
EntranceClosingTime = configData.EntranceClosingTime,
CurrencyType = configData.CurrencyType,
CurrencyCount = configData.CurrencyCount,
TPSGuideURL = configData.TPSGuideURL
});
if (false == MetaData.Instance._BattleFFARewardMetaTable.TryGetValue(m_pod_combat_reward_group_id, out var rewardMeta))
{
var err_msg = $"Not exist reward Meta Data id : {m_pod_combat_ffa_id}";
Log.getLogger().error(err_msg);
NullReferenceCheckHelper.throwIfNull(rewardMeta, () => $"rewardMeta is null !!!");
}
foreach (var meta_set in rewardMeta)
{
var val = meta_set.Value;
var key = meta_set.Key;
BattleFFARewardData data = new BattleFFARewardData(new BattleFFARewardDataMutable()
{
Id = val.Id,
GroupID = val.GroupID,
ChargeLevel = val.ChargeLevel,
ChargeTime = val.ChargeTime,
RewardItemID = val.RewardItemID,
RewardCount = val.RewardCount
});
m_ffa_reward_meta.TryAdd(key, data);
}
Log.getLogger().info($"BattleInstanceRoom construct done roomId : " +
$"{room.getMap().m_room_id}, eventStartTime : {eventStartTime}, configId : {configId}, rewardId : {rewardId}, hotTime : {hotTime}, roundCount : {roundCount}");
}
public async Task<Result> init()
{
string err_msg = string.Empty;
//Action 추가
addEntityAction(new BattleInstanceAction(this));
addEntityAction(new BattleInstanceUpdateAction(this));
addEntityAction(new BattleObjectInteractAction(this));
addEntityAction(new BattleObjectRewardAction(this));
//Attribute 추가
addEntityAttribute(new BattleInstanceSnapshotAttribute(this));
//Anchor 정보 로드
loadAnchorPos();
//스냅샷 데이터 로드, 없으면 신규 생성
var battle_instance_action = getEntityAction<BattleInstanceAction>();
NullReferenceCheckHelper.throwIfNull(battle_instance_action, () => $"battle_instance_action is null !!!");
var result = await battle_instance_action.loadOrCreateSnapshot();
if (result.isFail())
{
err_msg = $"loadSnapshot error instanceId : {m_instance_room.getInstanceId()}, roomId : {m_instance_room.getMap().m_room_id}";
Log.getLogger().error(err_msg);
return result;
}
Log.getLogger().info($"load Snapshot done instanceId : {m_instance_room.getInstanceId()}, roomId : {m_instance_room.getMap().m_room_id}");
//태스크 생성
result = await createTask();
if (result.isFail())
{
err_msg = $"battle instance room onCreateTask error instanceId : {m_instance_room.getInstanceId()}, roomId : {m_instance_room.getMap().m_room_id}";
Log.getLogger().error(err_msg);
return result;
}
Log.getLogger().info($"createTask done instanceId : {m_instance_room.getInstanceId()}, roomId : {m_instance_room.getMap().m_room_id}");
m_is_load_complete = true;
// P2P Host Migrator p2p 그룹 id 설정
m_host_migrator.setGroupHostId(m_instance_room.getMap().getP2PGroupId());
return result;
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
private async Task<Result> createTask()
{
var result = new Result();
//Timer에서 사용할 Action 초기화
var battle_update_action = getEntityAction<BattleInstanceUpdateAction>();
NullReferenceCheckHelper.throwIfNull(battle_update_action, () => $"battle_update_action is null !!!");
try
{
//임시로 0.8초로 처리 나중에 이거 Meta로 빼야 된다.
new PeriodicTaskTimer( GetType().Name, BattleConstant.BATTLE_ROOM_CHECK_INTERVAL, m_cancel_token, onTaskTick);
await battle_update_action.onInit();
Log.getLogger().debug("battle_update_action.onInit() dome");
}
catch(Exception e)
{
var err_msg = $"Exception !!!, new PeriodicTaskTimer() : exception:{e} - {toBasicString()}";
result.setFail(ServerErrorCode.TryCatchException, err_msg);
return result;
}
return result;
}
private void loadAnchorPos()
{
foreach (var anchor_info_dict in m_instance_room.getMap().getAnchors())
{
var anchor_guid = anchor_info_dict.Key;
var anchor_info = anchor_info_dict.Value;
if (!MapDataTable.Instance.getAnchor(anchor_guid, out var anchor))
{
Log.getLogger().error($"anchr_guid not MapDataTable.Instance.getAnchor, anchorGuid : {anchor_guid}");
continue;
}
var type = anchor.Type;
var table_id = anchor_info.AnchorProp.TableId;
loadRespawnPos(type, anchor_guid);
loadBattleObjectGroups(type, anchor_guid, table_id);
}
}
private void loadRespawnPos(string type, string anchorGuid)
{
if (!type.Equals(BattleConstant.RESPAWN_POS_ANCHOR_NAME)) return;
if (false == m_respawn_pos_anchors_meta.Add(anchorGuid))
{
Log.getLogger().warn($"respawnPos add fail type : {type}, anchorGuid : {anchorGuid}");
}
Log.getLogger().info($"respawnPos add success type : {type}, anchorGuid : {anchorGuid}");
}
// private void loadBattleObject(string type, string anchorGuid)
// {
// if (!type.Equals(BattleConstant.BATTLE_OBJECT_ANCHOR_NAME)) return;
//
// if (false == m_battle_object_anchors_meta.Add(anchorGuid))
// {
// Log.getLogger().warn($"m_battle_object_anchors add fail type : {type}, anchorGuid : {anchorGuid}");
// }
// Log.getLogger().info($"m_battle_object_anchors add success type : {type}, anchorGuid : {anchorGuid}");
// }
private bool loadBattleObjectGroups(string type, string anchorGuid, Int32 tableID)
{
if (!type.Equals(BattleConstant.BATTLE_OBJECT_GROUP_ANCHOR_NAME)) return true;
// if (false == m_battle_object_group_anchors_meta.Add(anchorGuid))
// {
// Log.getLogger().warn($"m_battle_object_group_anchors add fail type : {type}, anchorGuid : {anchorGuid}");
// }
// Log.getLogger().info($"m_battle_object_group_anchors add success type : {type}, anchorGuid : {anchorGuid}");
if (false == MetaData.Instance._BattleObjectSpawnGroupMetaTable.TryGetValue(tableID, out var battle_object_spawn_meta))
{
Log.getLogger().warn($"battle_object_group add fail type : {type}, anchorGuid : {anchorGuid}, table_id : {tableID}");
return false;
}
var battle_object_id = battle_object_spawn_meta.BattleObjectID;
if (false == MetaData.Instance._BattleObjectMetaTable.TryGetValue(battle_object_id, out var battle_object_meta))
{
Log.getLogger().warn($"battle_object_group add fail type : {type}, anchorGuid : {anchorGuid}, table_id : {tableID}, battle_object_id : {battle_object_id}");
return false;
}
EBattleObjectType object_type = battle_object_meta.ObjectType;
var group_id = battle_object_spawn_meta.GroupID;
if (object_type.Equals(EBattleObjectType.Pod_Combat) && battle_object_meta.Name.Equals(BattleConstant.BATTLE_POD_STORAGE_NAME))
{
loadBattleObjectPodStorageGroup(anchorGuid, group_id);
}
else if (object_type.Equals(EBattleObjectType.Pod_Box))
{
loadBattleObjectPickupPodGroup(anchorGuid, group_id);
}
return true;
}
private void loadBattleObjectPodStorageGroup(string anchorGuid, int groupId)
{
if (false == m_battle_pod_storage_guid_group.ContainsKey(groupId))
{
m_battle_pod_storage_guid_group.TryAdd(groupId, new());
}
if (false == m_battle_pod_storage_guid_group.TryGetValue(groupId, out var poses))
{
Log.getLogger().error($"m_battle_pod_stand_group_pos_meta get fail anchorGuid : {anchorGuid}, group_id : {groupId}");
return;
}
poses.Add(anchorGuid);
Log.getLogger().info($"m_battle_pod_stand_group_pos_meta Add anchorGuid : {anchorGuid}, group_id : {groupId}");
}
private void loadBattleObjectPickupPodGroup(string anchorGuid, int groupId)
{
if (false == m_battle_pickup_pod_guid_group.ContainsKey(groupId))
{
m_battle_pickup_pod_guid_group.TryAdd(groupId, new());
}
if (false == m_battle_pickup_pod_guid_group.TryGetValue(groupId, out var poses))
{
Log.getLogger().error($"m_battle_pod_box_group_pos_meta get fail anchorGuid : {anchorGuid}, group_id : {groupId}");
return;
}
poses.Add(anchorGuid);
Log.getLogger().info($"m_battle_pod_box_group_pos_meta Add anchorGuid : {anchorGuid}, group_id : {groupId}");
}
public Result AddOrUpdatePlayer(Player player)
{
var result = new Result();
// if (false == m_battle_players.TryAdd(player.getUserGuid(), new BattlePlayer(player)))
// {
// string err_msg = $"Player tryAdd fail guid : {player.getUserGuid()}";
// result.setFail(ServerErrorCode.BattleInstanceJoinPlayerError, err_msg);
// Log.getLogger().error(result.toBasicString());
// return result;
// }
return result;
}
private async Task onTaskTick()
{
if (!m_is_load_complete) return;
var battle_update_action = getEntityAction<BattleInstanceUpdateAction>();
NullReferenceCheckHelper.throwIfNull(battle_update_action, () => $"battle_update_action is null !!!");
var result = await battle_update_action.update();
if (result.isFail())
{
var err_msg = $"playr mode hander update error : {result.toBasicString()}";
Log.getLogger().error(err_msg);
}
}
public ILogActor toLogActor()
{
var server_logic = GameServerApp.getServerLogic();
var region_id = server_logic.getServerConfig().getRegionId();
var server_name = server_logic.getServerName();
var log_info = new BattleInstanceActorLog(region_id, server_name, m_instance_room.getMap().m_room_id, m_instance_room.getInstanceId());
return log_info;
}
public async Task removePodCombat(Player player)
{
var attribute = getEntityAttribute<BattleInstanceSnapshotAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"attribute is null !!!");
if (attribute.m_combat_pod_mode.m_pod_combat.m_current_occupier_guid.Equals(player.getUserGuid()))
{
using (var releaser = await getAsyncLock())
{
attribute.m_combat_pod_mode.m_pod_combat.changeDropState(player.getCurrentPositionInfo().Pos);
}
BattleRoomNotifyHelper.broadcast_GS2C_NTF_POD_COMBAT_STATE(this);
}
}
public void removeBattlePlayerIfExist(string userGuid)
{
// if (true == m_battle_players.ContainsKey(userGuid))
// {
// if (false == m_battle_players.TryRemove(userGuid, out var player))
// {
// Log.getLogger().warn($"m_battle_players try remove faial userGuid : {userGuid}");
// }
// }
}
public async Task<bool> LeaveBattleRoom(Player player, string roomId, bool disconnected = false)
{
//BattleRoom에서 먼저 빼준다.
//m_battle_players.TryRemove(player.getUserGuid(), out _);
Log.getLogger().info($"LeaveBattleRoom, player : {player.toBasicString()}, roomId : {roomId}, disconnected : {disconnected}");
await m_instance_room.LeaveBattleInstanceRoom(player, disconnected);
if (m_instance_room.isDestroy)
{
Log.getLogger().info($"m_instance_room.isDestroy, so destroyBattleRoom : {player.toBasicString()}, roomId : {roomId}, disconnected : {disconnected}");
await destroyBattleRoom();
InstanceRoomManager.Instance.DestroyRoom(roomId);
Log.getLogger().info($"destroy InstanceRoomManager room Player : {player.toBasicString()}, roomId : {roomId}, disconnected : {disconnected}");
}
return true;
}
public async Task destroyBattleRoom()
{
await Task.CompletedTask;
//여기서 timer 종료 처리
m_cancel_token.Cancel();
Log.getLogger().debug($"battle instance room token canceled m_room_id :{m_instance_room.getMap().m_room_id}");
var fn_save_battle_instance = async delegate()
{
var server_logic = GameServerApp.getServerLogic();
var fn_result = new Result();
using (var releaser = await getAsyncLock())
{
//여기서 battleRoomSnapshot 저장
var battle_instance_snapshot_attribute = getEntityAttribute<BattleInstanceSnapshotAttribute>();
NullReferenceCheckHelper.throwIfNull(battle_instance_snapshot_attribute, () => $"battle_instance_snapshot_attribute is null !!!");
if (!battle_instance_snapshot_attribute.m_combat_pod_mode.m_pod_combat.m_current_occupier_guid.Equals(string.Empty))
{
battle_instance_snapshot_attribute.m_combat_pod_mode.m_pod_combat.m_current_occupier_guid = string.Empty;
}
battle_instance_snapshot_attribute.modifiedEntityAttribute(true);
var batch = new QueryBatchEx<QueryRunnerWithDocument>(this, LogActionType.BattleInstanceSnapshotSave, server_logic.getDynamoDbClient(), true);
{
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
}
BattleSnapShotBusinessLog business_log = new(this, "");
batch.appendBusinessLog(business_log);
fn_result = await QueryHelper.sendQueryAndBusinessLog(batch);
if (fn_result.isSuccess())
{
Log.getLogger().info($"save battle instance snapshot done attribute : {JsonConvert.SerializeObject(battle_instance_snapshot_attribute)}");
}
}
return fn_result;
};
var result = await runTransactionRunnerSafely(TransactionIdType.PrivateContents, "SaveBattleInstanceByDestroy", fn_save_battle_instance);
if (result.isFail())
{
var err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {toBasicString()}";
Log.getLogger().error(err_msg);
}
}
public override string toBasicString()
{
return $"BattleInstanceRoom room_id : {m_instance_room.getMap().m_room_id}";
}
public void setEventStartTime(DateTime t)
{
m_battle_instance_event_start_time = t;
}
}