405 lines
16 KiB
C#
405 lines
16 KiB
C#
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 BattleInstanceRoomHandler
|
|
{
|
|
private string m_user_guid = string.Empty;
|
|
private InstanceMetaData m_instance_meta_data = new(new InstanceMetaDataMutable());
|
|
public BattleInstanceRoomHandler(string userGuid, InstanceMetaData instanceMetaData)
|
|
{
|
|
m_user_guid = userGuid;
|
|
m_instance_meta_data = instanceMetaData;
|
|
}
|
|
|
|
public async Task<(Result, string)> joinBattleInstance(string userGuid, Int32 eventId, Timestamp eventStartTS, Int32 instanceMetaId) //BattleInstanceType battleInstanceType
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
var instance_room_storage = new InstanceRoomStorage();
|
|
instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
|
|
var instance_room_id = string.Empty;
|
|
|
|
(result, instance_room_id) = await joinBattleInstanceRoom(userGuid, eventId, eventStartTS);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to joinInstanceRoom() !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, string.Empty);
|
|
}
|
|
|
|
return (result, instance_room_id);
|
|
}
|
|
|
|
public async Task<(Result, string)> joinBattleInstanceRoom(string userGuid, Int32 eventId, Timestamp eventStartTS)
|
|
{
|
|
var result = new Result();
|
|
string err_msg;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
var instance_room_storage = new InstanceRoomStorage();
|
|
instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
|
|
long timestampInSeconds = eventStartTS.Seconds;
|
|
|
|
//long start_seqs_num = timestampInSeconds / 100; //방의 시퀀스번호를 정하는 시작 번호
|
|
int start_seqs_num = 1; //방의 시퀀스번호를 정하는 시작 번호
|
|
|
|
//인스턴스 이름 base로 들어가는 문자열 생성
|
|
var instance_room_id_base = makeBattleInstanceRoomIdBase(eventId, timestampInSeconds, m_instance_meta_data.Id);
|
|
var instance_room_id = string.Empty;
|
|
|
|
//1.전체 roomList,와 스코어를 먼저 가져온다.
|
|
var battle_instance_room_storage = new BattleInstanceRoomStorage();
|
|
battle_instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
(result, var total_room_list) = await battle_instance_room_storage.getBattleInstanceTotalRoomListWithScore(instance_room_id_base, m_instance_meta_data.LimitCount);
|
|
if (result.isFail() || total_room_list == null)
|
|
{
|
|
return (result, string.Empty);
|
|
}
|
|
|
|
var ordered_available_room = await battle_instance_room_storage.getBattleInstanceRoomList(instance_room_id_base, m_instance_meta_data.LimitCount);
|
|
var total_room_length = total_room_list.Length;
|
|
|
|
Log.getLogger().info($"join battle instance.. room capacity state.. " +
|
|
$"totalroomlist : {JsonConvert.SerializeObject(total_room_list)}, available room : {JsonConvert.SerializeObject(ordered_available_room)}");
|
|
|
|
//total_room_list가 없고 비어있는 방도 없으면, 신규 생성
|
|
if(total_room_length == 0 && ordered_available_room.Count == 0)
|
|
{
|
|
(result, instance_room_id) = await createAndJoinBattleInstance(instance_room_id_base, start_seqs_num, userGuid);
|
|
if (result.isFail()) return (result, instance_room_id);
|
|
Log.getLogger().info($"join battle instance..make new first room instance_room_id : {instance_room_id}");
|
|
}
|
|
//기존 방은 있으나 지금 입장 가능한 방이 없는경우 모든 방이 풀방이므로 비어있는 시퀀스 찾아서 방생성
|
|
else if (total_room_length > 0 && ordered_available_room.Count == 0)
|
|
{
|
|
//total_room_list 에서 생성되어 있는 roomSeq를 확인한다.
|
|
HashSet<Int32> using_room_seqs = new();
|
|
|
|
foreach (var room_entry in total_room_list)
|
|
{
|
|
var room_id = room_entry.Element.ToString();
|
|
|
|
var room_element = room_id.Split(":");
|
|
if (false == int.TryParse(room_element[^1], out var seq))
|
|
{
|
|
err_msg = $"Failed to try parse room_element !!! room_id : {room_id}";
|
|
Log.getLogger().error(err_msg);
|
|
result.setFail(ServerErrorCode.BattleInstanceSeqParseError, err_msg);
|
|
return (result, string.Empty);
|
|
}
|
|
using_room_seqs.Add(seq);
|
|
}
|
|
|
|
var not_using_seq = findNotUsingSeqNum(using_room_seqs, start_seqs_num);
|
|
|
|
(result, instance_room_id) = await createAndJoinBattleInstance(instance_room_id_base, not_using_seq, userGuid);
|
|
if (result.isFail()) return (result, instance_room_id);
|
|
|
|
Log.getLogger().info($"join battle instance..make new another room instance_room_id : {instance_room_id}");
|
|
}
|
|
//비어 있는 방이 있는 경우
|
|
else if(ordered_available_room.Count > 0)
|
|
{
|
|
//빈방이 있는 경우 로직 처리
|
|
foreach (var room_id in ordered_available_room)
|
|
{
|
|
var instance_room_Info = await instance_room_storage.GetInstanceRoomInfo(room_id);
|
|
if (instance_room_Info == null)
|
|
{
|
|
await InstanceRoomHandler.deleteInstanceRoom(room_id);
|
|
continue;
|
|
}
|
|
|
|
result = await joinBattleInstanceRoomFromRedis(userGuid, room_id, instance_room_id_base);
|
|
if (result.isSuccess())
|
|
{
|
|
instance_room_id = room_id;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Log.getLogger().info($"join battle instance..join exists room instance_room_id : {instance_room_id}");
|
|
}
|
|
|
|
if (instance_room_id == string.Empty)
|
|
{
|
|
var new_seq = total_room_length + 1;
|
|
//위 로직을 전부 태웠는데도 방이 안만들어졌으면 전체 방수 + 1해서 만든다...
|
|
Log.getLogger().warn($"instance room id is still empty... so make new instance instance_room_id_base : {instance_room_id_base}, new_seq : {new_seq}");
|
|
(result, instance_room_id) = await createAndJoinBattleInstance(instance_room_id_base, new_seq, userGuid);
|
|
}
|
|
|
|
return (result, instance_room_id);
|
|
}
|
|
|
|
private async Task<(Result, string)> createAndJoinBattleInstance(string instanceRoomIdBase, int seq, string userGuid)
|
|
{
|
|
string err_msg = string.Empty;
|
|
(var result, var instance_room_id) = await createBattleInstanceRoomFromRedis(instanceRoomIdBase, m_instance_meta_data.Id, seq);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to createInstanceRoomFromRedis() !!! : {result.toBasicString()} - userGuid:{userGuid}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, string.Empty);
|
|
}
|
|
|
|
result = await joinBattleInstanceRoomFromRedis(userGuid, instance_room_id, instanceRoomIdBase);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to joinInstanceRoomFromRedis() !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, string.Empty);
|
|
}
|
|
|
|
Log.getLogger().info($"create and join battle instance instanceRoomIdBase : {instanceRoomIdBase}, seq : {seq}, userGuid : {userGuid}");
|
|
|
|
return (result, instance_room_id);
|
|
|
|
}
|
|
|
|
private int findNotUsingSeqNum(HashSet<Int32> usingRoomSeqs, int startSeqNum)
|
|
{
|
|
var loop_count = usingRoomSeqs.Count + 1;
|
|
|
|
var start_seq = startSeqNum;
|
|
|
|
for (int i = 1; i <= loop_count; i++)
|
|
{
|
|
if (usingRoomSeqs.Contains(start_seq))
|
|
{
|
|
start_seq++;
|
|
continue;
|
|
}
|
|
|
|
return start_seq;
|
|
}
|
|
|
|
return start_seq;
|
|
}
|
|
|
|
public async Task<(Result, string)> createBattleInstanceRoomFromRedis(string instanceRoomIdBase, int instanceMetaId, int startSeqsNum)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
var instance_room_storage = new InstanceRoomStorage();
|
|
instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
|
|
(result, var instance_server_info) = await InstanceRoomHandler.getBestInstanceServerForCreateInstance(m_instance_meta_data.LimitCount);
|
|
if (result.isFail() || instance_server_info == null)
|
|
{
|
|
err_msg = $"Failed to getBestInstanceServerForCreateInstance() !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, string.Empty);
|
|
}
|
|
|
|
if (instance_server_info.Address == string.Empty || instance_server_info.Port == 0)
|
|
{
|
|
err_msg = $"ServerInfo is invalid !!! Address:{instance_server_info.Address}, Port:{instance_server_info.Port}";
|
|
result.setFail(ServerErrorCode.ValidServerNotFound, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, string.Empty);
|
|
}
|
|
|
|
var instance_room_id = makeBattleInstanceRoomId(instanceRoomIdBase, startSeqsNum);
|
|
|
|
(result, var is_created) = await instance_room_storage.createInstanceRoom(instance_room_id, instance_server_info.Address, instance_server_info.Port, instanceMetaId);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to createInstanceRoom() !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, string.Empty);
|
|
}
|
|
|
|
if (is_created)
|
|
{
|
|
|
|
var battle_instance_room_storage = new BattleInstanceRoomStorage();
|
|
battle_instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
result = await battle_instance_room_storage.addBattleInstanceRoomList(instanceRoomIdBase, instance_room_id);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to addInstanceRoomList() !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, string.Empty);
|
|
}
|
|
}
|
|
|
|
return (result, instance_room_id);
|
|
}
|
|
|
|
public static string makeBattleInstanceRoomIdBase(Int32 eventId, long timestampInSeconds, Int32 instanceId)
|
|
{
|
|
if (eventId == 0)
|
|
{
|
|
return $"{BattleConstant.PREFIX_BATTLE_INSTANCE_ROOM_ID}:{eventId}_1234567890_{instanceId}";
|
|
}
|
|
|
|
return $"{BattleConstant.PREFIX_BATTLE_INSTANCE_ROOM_ID}:{eventId}_{timestampInSeconds}_{instanceId}";
|
|
}
|
|
|
|
static string makeBattleInstanceRoomId(string instanceRoomIdBase, int startSeqsNum)
|
|
{
|
|
//var server_logic = GameServerApp.getServerLogic();
|
|
//var instance_room_storage = new InstanceRoomStorage();
|
|
// instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
// var room_id_seq = await instance_room_storage.getRoomIdSeq();
|
|
// if (room_id_seq == 0)
|
|
// return string.Empty;
|
|
|
|
return $"{instanceRoomIdBase}:{startSeqsNum}";
|
|
}
|
|
|
|
|
|
// async Task<(Result, string)> joinBattleInstanceRoom(string userGuid, BattleInstanceType instanceType, int instanceMetaId)
|
|
// {
|
|
// var result = new Result();
|
|
// string err_msg;
|
|
//
|
|
// var server_logic = GameServerApp.getServerLogic();
|
|
//
|
|
// var battle_instance_room_storage = new BattleInstanceRoomStorage();
|
|
// battle_instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
//
|
|
// if (!MetaData.Instance._IndunTable.TryGetValue(instanceMetaId, out var instance_meta_data))
|
|
// {
|
|
// err_msg = $"Failed to MetaData.TryGetValue() !!! : instanceMetaId:{instanceMetaId} - userGuid:{userGuid}";
|
|
// result.setFail(ServerErrorCode.InstanceMetaDataNotFound, err_msg);
|
|
// Log.getLogger().error(result.toBasicString());
|
|
//
|
|
// return (result, string.Empty);
|
|
// }
|
|
// var instance_room_id_base = makeBattleInstanceRoomIdBase(instanceType, instanceMetaId);
|
|
// var instance_room_id = string.Empty;
|
|
//
|
|
// //인스턴스 정보가 redis에 없으면 roomlist에서 제거 처리
|
|
// var room_list = await instance_room_storage.GetInstanceRoomList(instance_room_id_base, instance_meta_data.LimitCount);
|
|
// foreach (var room_id in room_list)
|
|
// {
|
|
// var instance_room_Info = await instance_room_storage.GetInstanceRoomInfo(room_id);
|
|
// if (instance_room_Info == null)
|
|
// {
|
|
// await InstanceRoomHandler.deleteInstanceRoom(room_id);
|
|
// continue;
|
|
// }
|
|
//
|
|
// result = await joinBattleInstanceRoomFromRedis(userGuid, room_id, instanceMetaId, instance_room_id_base, instance_room_Info.UgcNpcCount);
|
|
// if (result.isSuccess())
|
|
// {
|
|
// instance_room_id = room_id;
|
|
// break;
|
|
// }
|
|
// }
|
|
//
|
|
// if (instance_room_id == string.Empty)
|
|
// {
|
|
// (result, instance_room_id) = await createBattleInstanceRoomFromRedis(instance_room_id_base, instanceMetaId);
|
|
// if (result.isFail())
|
|
// {
|
|
// err_msg = $"Failed to createInstanceRoomFromRedis() !!! : {result.toBasicString()} - userGuid:{userGuid}";
|
|
// Log.getLogger().error(err_msg);
|
|
//
|
|
// return (result, string.Empty);
|
|
// }
|
|
//
|
|
// result = await joinBattleInstanceRoomFromRedis(userGuid, instance_room_id, instanceMetaId, instance_room_id_base, 0);
|
|
// if (result.isFail())
|
|
// {
|
|
// err_msg = $"Failed to joinInstanceRoomFromRedis() !!! : {result.toBasicString()}";
|
|
// Log.getLogger().error(err_msg);
|
|
//
|
|
// return (result, string.Empty);
|
|
// }
|
|
// }
|
|
//
|
|
// return (result, instance_room_id);
|
|
// }
|
|
public async Task<Result> joinBattleInstanceRoomFromRedis(string userGuid, string instanceRoomId, string instanceRoomIdBase)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
var instance_room_storage = new InstanceRoomStorage();
|
|
instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
|
|
result = await instance_room_storage.joinInstanceRoom(userGuid, instanceRoomId, m_instance_meta_data.LimitCount);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to TryJoinInstanceRoom() !!! : {result.toBasicString()}";
|
|
Log.getLogger().debug(err_msg);
|
|
|
|
return result;
|
|
}
|
|
|
|
result = await instance_room_storage.increaseInstanceRoomScore(instanceRoomIdBase, instanceRoomId);
|
|
if (result.isFail())
|
|
{
|
|
await instance_room_storage.leaveInstanceRoom(userGuid, instanceRoomId);
|
|
|
|
err_msg = $"Failed to increaseInstanceRoomScore() !!! : {result.toBasicString()} - userGuid:{userGuid}";
|
|
Log.getLogger().debug(err_msg);
|
|
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
public static async Task<Result> leaveBattleInstanceRoom(string userGuid, string instanceRoomId)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
var instance_room_storage = new InstanceRoomStorage();
|
|
instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
|
|
await instance_room_storage.leaveInstanceRoom(userGuid, instanceRoomId);
|
|
|
|
var instance_room_id_base = getInstanceRoomIdBaseFromInstanceRoomId(instanceRoomId);
|
|
await instance_room_storage.decreaseInstanceRoomScore(instance_room_id_base, instanceRoomId);
|
|
|
|
return result;
|
|
}
|
|
|
|
public static string getInstanceRoomIdBaseFromInstanceRoomId(string instanceRoomId)
|
|
{
|
|
var instance_room_Id_element = instanceRoomId.Split(":");
|
|
|
|
if (instance_room_Id_element.Length >= 2)
|
|
{
|
|
return $"{instance_room_Id_element[0]}:{instance_room_Id_element[1]}";
|
|
}
|
|
Log.getLogger().error($"Instance room id weired : {instanceRoomId}");
|
|
return string.Empty;
|
|
}
|
|
} |