- 채널 입장 시 API 서버에서 플레이어 프로필 로드 (레벨/스탯/위치) - 채널 퇴장 시 위치/플레이타임 DB 저장 (SaveGameDataAsync) - Player.cs에 AttackPower/AttackRange/SprintMultiplier/Experience 필드 추가 - ToPlayerInfo에서 전투 스탯 매핑 추가 - Session에 ChannelJoinedAt 추가 (플레이타임 계산용) - PartyUpdateType에 INVITE/KICK 추가 - RequestPartyPacket에 TargetPlayerId 필드 추가 - GameServer에 INVITE/KICK 핸들러 구현 - Channel에 GetPeer() 메서드 추가 - RestApi에 GetPlayerProfileAsync/SaveGameDataAsync 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
1.6 KiB
C#
84 lines
1.6 KiB
C#
using LiteNetLib;
|
|
|
|
namespace ServerLib.Service;
|
|
|
|
public class Session
|
|
{
|
|
public string? Token
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public string? Username
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public int HashKey
|
|
{
|
|
get;
|
|
init;
|
|
}
|
|
|
|
public NetPeer Peer
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
// 패킷 레이트 리미팅
|
|
private int packetCount;
|
|
private long windowStartTicks;
|
|
|
|
// 초당 허용 패킷 수
|
|
public int MaxPacketsPerSecond { get; set; }
|
|
|
|
// 연속 초과 횟수
|
|
public int RateLimitViolations { get; private set; }
|
|
|
|
// 패킷 수신 시 호출. 초당 제한 초과 시 true 반환.
|
|
public bool CheckRateLimit()
|
|
{
|
|
long now = Environment.TickCount64;
|
|
|
|
// 1초(1000ms) 윈도우 초과 시 리셋
|
|
if (now - windowStartTicks >= 1000)
|
|
{
|
|
windowStartTicks = now;
|
|
packetCount = 0;
|
|
}
|
|
|
|
packetCount++;
|
|
|
|
if (packetCount > MaxPacketsPerSecond)
|
|
{
|
|
RateLimitViolations++;
|
|
return true; // 제한 초과
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// 위반 카운트 초기화
|
|
public void ResetViolations()
|
|
{
|
|
RateLimitViolations = 0;
|
|
}
|
|
|
|
// 채널 입장 시각 (플레이타임 계산용)
|
|
public DateTime ChannelJoinedAt { get; set; }
|
|
|
|
public Session(int hashKey, NetPeer peer, int maxPacketsPerSecond = 60)
|
|
{
|
|
HashKey = hashKey;
|
|
Peer = peer;
|
|
Token = null;
|
|
MaxPacketsPerSecond = maxPacketsPerSecond;
|
|
packetCount = 0;
|
|
windowStartTicks = Environment.TickCount64;
|
|
RateLimitViolations = 0;
|
|
}
|
|
}
|