T2FGame.Room
1.0.9
dotnet add package T2FGame.Room --version 1.0.9
NuGet\Install-Package T2FGame.Room -Version 1.0.9
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="T2FGame.Room" Version="1.0.9" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="T2FGame.Room" Version="1.0.9" />
<PackageReference Include="T2FGame.Room" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add T2FGame.Room --version 1.0.9
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: T2FGame.Room, 1.0.9"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package T2FGame.Room@1.0.9
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=T2FGame.Room&version=1.0.9
#tool nuget:?package=T2FGame.Room&version=1.0.9
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
T2FGame.Room
T2FGame 框架的房间模块,提供类似 ioGame 的游戏房间管理功能。
功能特性
- 房间管理:创建、加入、离开、解散房间
- 玩家管理:房间内玩家状态管理
- 房间广播:向房间内所有/部分玩家发送消息
- 匹配系统:支持快速匹配和自定义匹配
- 房间状态机:等待、游戏中、结算等状态流转
安装
<PackageReference Include="T2FGame.Room" />
核心概念
房间生命周期
Created → Waiting → Playing → Settling → Closed
│ │ ▲
│ │ (游戏结束) │
│ └──────────────────────────────┘
│ (所有人离开)
└───────────────────────────────────────────→
快速开始
1. 定义房间类型
public class BattleRoom : GameRoom<BattleRoomPlayer>
{
public int MaxRounds { get; set; } = 3;
public int CurrentRound { get; private set; }
protected override void OnPlayerJoin(BattleRoomPlayer player)
{
// 玩家加入房间时的逻辑
BroadcastToAll(new PlayerJoinNotify { PlayerId = player.PlayerId });
}
protected override void OnPlayerLeave(BattleRoomPlayer player)
{
// 玩家离开房间时的逻辑
BroadcastToAll(new PlayerLeaveNotify { PlayerId = player.PlayerId });
}
public void StartGame()
{
if (State != RoomState.Waiting) return;
if (PlayerCount < MinPlayers) return;
State = RoomState.Playing;
CurrentRound = 1;
BroadcastToAll(new GameStartNotify { Round = CurrentRound });
}
}
public class BattleRoomPlayer : RoomPlayer
{
public int Score { get; set; }
public bool IsReady { get; set; }
public int TeamId { get; set; }
}
2. 配置房间服务
services.AddT2FGameRoom(options =>
{
options.MaxRoomsPerServer = 1000;
options.DefaultMaxPlayers = 4;
options.RoomIdleTimeout = TimeSpan.FromMinutes(30);
});
// 注册房间类型
services.AddRoomType<BattleRoom, BattleRoomPlayer>("battle");
services.AddRoomType<LobbyRoom, LobbyPlayer>("lobby");
核心组件
GameRoom(游戏房间)
public abstract class GameRoom<TPlayer> where TPlayer : RoomPlayer
{
// 基本属性
public string RoomId { get; }
public string RoomType { get; }
public RoomState State { get; protected set; }
public long OwnerId { get; protected set; }
// 容量设置
public int MaxPlayers { get; set; }
public int MinPlayers { get; set; }
public int PlayerCount { get; }
public bool IsFull { get; }
// 玩家管理
public TPlayer? GetPlayer(long playerId);
public IReadOnlyList<TPlayer> GetAllPlayers();
public bool HasPlayer(long playerId);
// 加入/离开
public virtual Result Join(TPlayer player);
public virtual Result Leave(long playerId);
// 广播
public void BroadcastToAll(IMessage message);
public void BroadcastToOthers(long excludePlayerId, IMessage message);
public void BroadcastToTeam(int teamId, IMessage message);
public void SendToPlayer(long playerId, IMessage message);
// 生命周期钩子
protected virtual void OnPlayerJoin(TPlayer player) { }
protected virtual void OnPlayerLeave(TPlayer player) { }
protected virtual void OnRoomClose() { }
}
RoomPlayer(房间玩家)
public class RoomPlayer
{
public long PlayerId { get; set; }
public string Nickname { get; set; }
public int Seat { get; set; }
public PlayerState State { get; set; }
public DateTime JoinTime { get; set; }
// 自定义数据
public Dictionary<string, object> Properties { get; }
}
public enum PlayerState
{
Idle, // 空闲
Ready, // 准备
Playing, // 游戏中
Offline // 离线
}
RoomManager(房间管理器)
public interface IRoomManager
{
// 创建房间
Task<Result<TRoom>> CreateRoomAsync<TRoom, TPlayer>(
long ownerId,
Action<TRoom>? configure = null)
where TRoom : GameRoom<TPlayer>, new()
where TPlayer : RoomPlayer;
// 获取房间
Task<GameRoom<TPlayer>?> GetRoomAsync<TPlayer>(string roomId)
where TPlayer : RoomPlayer;
// 查找玩家所在房间
Task<string?> GetPlayerRoomIdAsync(long playerId);
// 加入房间
Task<Result> JoinRoomAsync<TPlayer>(
string roomId,
TPlayer player)
where TPlayer : RoomPlayer;
// 离开房间
Task<Result> LeaveRoomAsync(string roomId, long playerId);
// 解散房间
Task<Result> DisbandRoomAsync(string roomId, long operatorId);
// 查询房间列表
Task<IReadOnlyList<RoomInfo>> GetRoomListAsync(
string roomType,
RoomQueryFilter? filter = null);
}
房间 Action
[ActionController(cmd: CmdModule.Room)]
public class RoomController
{
private readonly IRoomManager _roomManager;
[ActionMethod(subCmd: RoomCmd.Create)]
public async Task<CreateRoomResponse> CreateRoom(
CreateRoomRequest request,
FlowContext context)
{
var result = await _roomManager.CreateRoomAsync<BattleRoom, BattleRoomPlayer>(
context.UserId,
room =>
{
room.MaxPlayers = request.MaxPlayers;
room.RoomName = request.RoomName;
});
return result.Match(
room => new CreateRoomResponse { RoomId = room.RoomId },
error => throw new GameException(error));
}
[ActionMethod(subCmd: RoomCmd.Join)]
public async Task<JoinRoomResponse> JoinRoom(
JoinRoomRequest request,
FlowContext context)
{
var player = new BattleRoomPlayer
{
PlayerId = context.UserId,
Nickname = request.Nickname
};
var result = await _roomManager.JoinRoomAsync(request.RoomId, player);
return result.Match(
_ => new JoinRoomResponse { Success = true },
error => new JoinRoomResponse { ErrorCode = error.Code });
}
[ActionMethod(subCmd: RoomCmd.Leave)]
public async Task<LeaveRoomResponse> LeaveRoom(FlowContext context)
{
var roomId = await _roomManager.GetPlayerRoomIdAsync(context.UserId);
if (roomId == null)
return new LeaveRoomResponse { ErrorCode = "NotInRoom" };
await _roomManager.LeaveRoomAsync(roomId, context.UserId);
return new LeaveRoomResponse { Success = true };
}
}
匹配系统
匹配请求
[ActionMethod(subCmd: RoomCmd.QuickMatch)]
public async Task<MatchResponse> QuickMatch(
MatchRequest request,
FlowContext context)
{
var result = await _matchService.RequestMatchAsync(new MatchTicket
{
PlayerId = context.UserId,
RoomType = request.RoomType,
MatchMode = request.MatchMode,
Rating = request.Rating,
Preferences = request.Preferences
});
return new MatchResponse { TicketId = result.TicketId };
}
匹配结果通知
// 匹配成功后推送给所有匹配到的玩家
await BroadcastToPlayers(matchedPlayerIds, new MatchSuccessNotify
{
RoomId = room.RoomId,
Players = matchedPlayers.Select(p => p.ToProto())
});
房间状态
public enum RoomState
{
Created, // 已创建
Waiting, // 等待中
Starting, // 启动中
Playing, // 游戏中
Paused, // 暂停
Settling, // 结算中
Closed // 已关闭
}
房间事件
// 房间事件定义
public record RoomCreatedEvent(string RoomId, string RoomType, long OwnerId) : IDomainEvent;
public record PlayerJoinedRoomEvent(string RoomId, long PlayerId) : IDomainEvent;
public record PlayerLeftRoomEvent(string RoomId, long PlayerId) : IDomainEvent;
public record RoomStateChangedEvent(string RoomId, RoomState OldState, RoomState NewState) : IDomainEvent;
public record RoomClosedEvent(string RoomId) : IDomainEvent;
// 事件处理器
public class RoomEventHandler :
IEventHandler<PlayerJoinedRoomEvent>,
IEventHandler<PlayerLeftRoomEvent>
{
public async Task HandleAsync(PlayerJoinedRoomEvent @event, CancellationToken ct)
{
// 记录日志、更新统计等
}
public async Task HandleAsync(PlayerLeftRoomEvent @event, CancellationToken ct)
{
// 检查房间是否需要关闭等
}
}
目录结构
T2FGame.Room/
├── Configuration/
│ └── RoomOptions.cs # 房间配置
├── Core/
│ ├── GameRoom.cs # 房间基类
│ ├── RoomPlayer.cs # 房间玩家
│ ├── RoomState.cs # 房间状态
│ └── RoomInfo.cs # 房间信息
├── Management/
│ ├── IRoomManager.cs # 房间管理接口
│ ├── RoomManager.cs # 房间管理实现
│ └── RoomRegistry.cs # 房间注册表
├── Matching/
│ ├── IMatchService.cs # 匹配服务接口
│ ├── MatchService.cs # 匹配服务实现
│ └── MatchTicket.cs # 匹配票据
├── Events/
│ └── RoomEvents.cs # 房间事件定义
└── Extensions/
└── ServiceCollectionExtensions.cs # 服务注册
最佳实践
- 房间 ID 生成:使用有意义的前缀 + UUID,便于调试
- 玩家状态同步:使用增量更新而非全量同步
- 掉线重连:保留玩家位置一段时间,支持重连
- 房间清理:定期清理空闲房间,释放资源
- 并发控制:房间内操作使用锁或队列保证顺序
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net9.0
- T2FGame.Action (>= 1.0.9)
- T2FGame.Core (>= 1.0.9)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on T2FGame.Room:
| Package | Downloads |
|---|---|
|
T2FGame
T2FGame Framework - A high-performance distributed game server framework inspired by ioGame. This meta-package includes all T2FGame components. |
GitHub repositories
This package is not used by any popular GitHub repositories.