초기커밋

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,124 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using ServerCore;
using ServerBase;
using ServerCommon;
namespace GameServer;
public class RoomAction : EntityActionBase
{
private readonly ConcurrentDictionary<int, Room> m_rooms = new();
public RoomAction(Player owner) : base(owner)
{}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
private Room? getRoom(int room_id) => m_rooms.GetValueOrDefault(room_id);
public bool IsExist(int roomId)
{
return m_rooms.ContainsKey(roomId);
}
public async Task<Result> setRoomFromDoc(RoomDoc docBase)
{
var result = new Result();
string err_msg;
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var doc_attr = docBase.getAttrib<RoomAttrib>();
if (null == doc_attr)
{
err_msg = $"Fail to get doc attrib : {nameof(RoomAttrib)} is null";
result.setFail(ServerErrorCode.EntityAttributeNotFound, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// db 에서 설정하는 것으로, 없으면 생성해야 한다.
var room = getRoom(doc_attr.RoomId);
if (null == room)
{
room = new Room(owner);
m_rooms.TryAdd(doc_attr.RoomId, room);
}
var room_attribute = room.getEntityAttribute<RoomAttribute>();
if (null == room_attribute)
{
err_msg = $"Fail to get entity attribute : {nameof(RoomAttribute)} is null";
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// doc 에서 직접 copy 된 경우 pk, sk 를 셋팅해야 한다.
docBase.setCombinationKeyForPK(owner.getUserGuid());
docBase.setCombinationKeyForSK(doc_attr.RoomId.ToString());
var is_apply = docBase.onApplyPKSK();
if (ServerErrorCode.Success != is_apply)
{
err_msg = $"Fail to copy to attribute from doc : invalid argument {nameof(setRoomFromDoc)}";
result.setFail(is_apply, err_msg);
Log.getLogger().error(err_msg);
return result;
}
var is_success = room_attribute.copyEntityAttributeFromDoc(docBase);
if (false == is_success)
{
err_msg = $"Fail to copy room attribute : to {nameof(RoomAttribute)} from {nameof(RoomDoc)}";
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
Log.getLogger().error(err_msg);
}
return await Task.FromResult(result);
}
public async Task<Result> notifyRoomsToClient()
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var notify_packet = new ClientToGame
{
Message = new ClientToGameMessage
{
OwnedRoomNoti = new ClientToGameMessage.Types.OwnedRoomNoti()
}
};
foreach (var room in m_rooms)
{
var room_content_action = room.Value.getEntityAction<RoomContentAction>();
var data = room_content_action?.toRoomData4Client();
if (null == data) continue;
notify_packet.Message.OwnedRoomNoti.RoomList.Add(data);
}
GameServerApp.getServerLogic().onSendPacket(owner, notify_packet);
return await Task.FromResult(new Result());
}
}

View File

@@ -0,0 +1,71 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace GameServer;
public class RoomContentAction : EntityActionBase
{
public RoomContentAction(Room owner) : base(owner)
{
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
public RoomInfo? toRoomData4Client()
{
var attribute = getOwner().getEntityAttribute<RoomAttribute>();
if (null == attribute)
{
return null;
}
var data = new RoomInfo
{
Id = attribute.RoomId,
Owner = attribute.Owner,
Name = attribute.Name,
Description = attribute.Description
};
foreach (var info in attribute.PropInfo)
{
var prop = new PropInfo();
prop.AnchorGuid = info.Key;
prop.TableId = info.Value.TableId;
data.PropList.Add(prop);
}
return data;
}
public async Task<Result> notifyChangeRoomToClientAndServers()
{
// todo (sangyeob.kim) : 값이 변경되면, 해당 데이터를 참조하는 곳에 notify 를 해줘야 한다.
// Client, 타 Servers , Building Contents 에서 관리하고 있는 Rooms
// ....
return await Task.FromResult(new Result());
}
}

View File

@@ -0,0 +1,95 @@

using ServerCore;
using ServerBase;
using ServerCommon;
namespace GameServer;
public class DBQRoomReadAll : QueryExecutorBase
{
private string m_pk { get; set; } = string.Empty;
private readonly string m_combination_key_for_pk;
private readonly List<RoomDoc> m_to_read_room_docs = new();
public DBQRoomReadAll(string combinationKeyForPk) : base(nameof(DBQRoomReadAll))
{
m_combination_key_for_pk = combinationKeyForPk;
}
//=====================================================================================
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
//=====================================================================================
public override async Task<Result> onPrepareQuery()
{
var result = new Result();
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var doc = new RoomDoc();
doc.setCombinationKeyForPK(m_combination_key_for_pk);
var error_code = doc.onApplyPKSK();
if (error_code.isFail())
{
var err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
m_pk = doc.getPK();
return await Task.FromResult(result);
}
//=====================================================================================
// onPrepareQuery()를 성공할 경우 호출된다.
//=====================================================================================
public override async Task<Result> onQuery()
{
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var query_batch = getQueryBatch();
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!!");
var db_connector = query_batch.getDynamoDbConnector();
var query_config = db_connector.makeQueryConfigForReadByPKSK(m_pk);
(result, var read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<RoomDoc>(query_config, eventTid: query_batch.getTransId());
if (result.isFail())
{
return result;
}
var room_action = owner.getEntityAction<RoomAction>();
NullReferenceCheckHelper.throwIfNull(room_action, () => $"room_action is null !!!");
foreach (var read_doc in read_docs)
{
result = await room_action.setRoomFromDoc(read_doc);
if (result.isFail()) return result;
m_to_read_room_docs.Add(read_doc);
}
return await Task.FromResult(result);
}
//=====================================================================================
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseCommit() => await Task.CompletedTask;
//=====================================================================================
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseRollback(Result errorResult) => await Task.CompletedTask;
private new Player? getOwner() => getQueryBatch()?.getLogActor() as Player;
}

View File

@@ -0,0 +1,77 @@
using ServerCommon;
using ServerCore; using ServerBase;
namespace GameServer.Contents.Room.DbQuery;
public class DBQRoomReadTarget : QueryExecutorBase
{
private string m_pk { get; set; } = string.Empty;
private string m_sk { get; set; }
private readonly string m_combination_key_for_pk;
private RoomDoc m_to_read_room_doc = new();
public DBQRoomReadTarget(string combinationKeyForPk, int room_id) : base(nameof(DBQRoomReadTarget))
{
m_combination_key_for_pk = combinationKeyForPk;
m_sk = room_id.ToString();
}
//=====================================================================================
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
//=====================================================================================
public override async Task<Result> onPrepareQuery()
{
var result = new Result();
var doc = new RoomDoc();
doc.setCombinationKeyForPK(m_combination_key_for_pk);
var error_code = doc.onApplyPKSK();
if (error_code.isFail())
{
var err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
m_pk = doc.getPK();
return await Task.FromResult(result);
}
//=====================================================================================
// onPrepareQuery()를 성공할 경우 호출된다.
//=====================================================================================
public override async Task<Result> onQuery()
{
var result = new Result();
var err_msg = string.Empty;
var query_batch = getQueryBatch();
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!!");
var db_connector = query_batch.getDynamoDbConnector();
var query_config = db_connector.makeQueryConfigForReadByPKSK(m_pk, m_sk);
(result, var read_doc) = await db_connector.simpleQueryDocTypeWithQueryOperationConfig<RoomDoc>(query_config, eventTid: query_batch.getTransId());
if (result.isFail()) return result;
// todo (sangyeob.kim): DBQReadTarget에서 획득한 doc을 필요로 하는 action 으로 보내야 한다.
// ....
m_to_read_room_doc = read_doc!;
return await Task.FromResult(new Result());
}
//=====================================================================================
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseCommit() => await Task.CompletedTask;
//=====================================================================================
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseRollback(Result errorResult) => await Task.CompletedTask;
}

View File

@@ -0,0 +1,111 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace GameServer.PacketHandler;
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_CHANGE_SCREEN_PAGE), typeof(ChangeScreenPagePacketHandler), typeof(GameLoginListener))]
public class ChangeScreenPagePacketHandler : PacketRecvHandler
{
public static void send_S2C_ACK_CHANGE_SCREEN_PAGE(Player? owner, Result result, int screenPageNo)
{
var ack_packet = new ClientToGame
{
Response = new ClientToGameRes
{
ErrorCode = result.ErrorCode,
AckChangeScreenPage = new ClientToGameRes.Types.GS2C_ACK_CHANGE_SCREEN_PAGE
{
ScreenPageNo = screenPageNo
}
}
};
GameServerApp.getServerLogic().onSendPacket(owner!, ack_packet);
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
{
await Task.CompletedTask;
var result = new Result();
string err_msg;
var player = entityWithSession as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
// 1. 기본 정보 체크
var request = (recvMessage as ClientToGame)?.Request.ReqChangeScreenPage;
if (null == request)
{
err_msg = $"Failed to get request type !!! : {nameof(ClientToGame.Request.ReqChangeScreenPage)}";
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
Log.getLogger().error(result.toBasicString());
send_S2C_ACK_CHANGE_SCREEN_PAGE(player, result, -1);
return result;
}
// 2. room id 확인
(result, var room_id) = checkCondition(player, request);
if (result.ErrorCode != ServerErrorCode.Success)
{
send_S2C_ACK_CHANGE_SCREEN_PAGE(player, result, -1);
return result;
}
// 3. room screen page 수정
var screen_page = InstanceRoomManager.Instance.changeScreenPage(room_id, request.IsCustom == BoolType.True, request.IsIncrease == BoolType.True, request.CustomPage);
if (screen_page < 0)
{
err_msg = $"failed to change screen page!! : roomId[{room_id}]";
result.setFail(ServerErrorCode.NotExistInstanceRoom, err_msg);
Log.getLogger().error(err_msg);
}
send_S2C_ACK_CHANGE_SCREEN_PAGE(player, result, screen_page);
return await Task.FromResult(result);
}
private (Result result, string room_id) checkCondition(Player player, ClientToGameReq.Types.C2GS_REQ_CHANGE_SCREEN_PAGE request)
{
var result = new Result();
string err_msg;
var location = player.getEntityAttribute<LocationAttribute>();
NullReferenceCheckHelper.throwIfNull(location, () => $"location is null !!!");
// 1. room id 체크
var room_id = location.CurrentIndunLocation.InstanceRoomId;
if (string.IsNullOrEmpty(room_id))
{
err_msg = "Failed to change screen page!! : user is not in room";
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
Log.getLogger().error(result.toBasicString());
send_S2C_ACK_CHANGE_SCREEN_PAGE(player, result, -1);
return (result, string.Empty);
}
// 2. 매개변수 체크
if (request.IsCustom == BoolType.True && request.CustomPage < 0)
{
err_msg = $"Failed to change screen page!! : invalid custom page number - {request.CustomPage}";
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
Log.getLogger().error(result.toBasicString());
send_S2C_ACK_CHANGE_SCREEN_PAGE(player, result, -1);
return (result, string.Empty);
}
return (result, room_id);
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServerCore;
using ServerBase;
using ServerCommon;
namespace GameServer;
public class Room : EntityBase
{
public Room(Player parent)
: base(EntityType.Room, parent)
{
onInit().GetAwaiter().GetResult();
}
public sealed override async Task<Result> onInit()
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
addEntityAttribute(new RoomAttribute(this, parent));
addEntityAction(new RoomContentAction(this));
return await base.onInit();
}
public override string toBasicString()
{
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
}
public override string toSummaryString()
{
return $"{this.getTypeName()} - {getRootParent().toBasicString()}";
}
}

View File

@@ -0,0 +1,48 @@
using Amazon.S3.Model;
using GameServer.PacketHandler;
using ServerCommon;
using ServerCore; using ServerBase;
namespace GameServer;
[ChatCommandAttribute("changepage", typeof(RoomCommandScreenPageChange), AuthAdminLevelType.Developer,
AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
internal class RoomCommandScreenPageChange : ChatCommandBase
{
public override async Task invoke(Player player, string token, string[] args)
{
var result = new Result();
if (args.Length < 2) return;
var isCustom = false;
var isIncrease = false;
var custromPage = -1;
if (false == bool.TryParse(args[0], out isCustom)) return;
if (false == isCustom)
{
if (false == bool.TryParse(args[1], out isIncrease)) return;
}
else
{
if(false == int.TryParse(args[1], out custromPage)) return;
}
Log.getLogger().debug("Meeting Room Change Page");
var location = player.getEntityAttribute<LocationAttribute>();
NullReferenceCheckHelper.throwIfNull(location, () => $"location is null !!! - {player.toBasicString()}");
var room_id = location.CurrentIndunLocation.InstanceRoomId;
if (string.IsNullOrEmpty(room_id)) return;
var screen_page_no = InstanceRoomManager.Instance.changeScreenPage(room_id, isCustom, isIncrease, custromPage);
Log.getLogger().debug($"Change Meeting Room Screen Page : {screen_page_no}");
if(screen_page_no < 0) result.setFail(ServerErrorCode.NotExistInstanceRoom, $"failed to change screen page!! : roomId[{room_id}]");
ChangeScreenPagePacketHandler.send_S2C_ACK_CHANGE_SCREEN_PAGE(player, result, screen_page_no);
await Task.CompletedTask;
}
}