新增逻辑

This commit is contained in:
2025-12-15 12:30:45 +08:00
parent a4c2bb021b
commit 240bee00c3
56 changed files with 649 additions and 526 deletions

View File

@@ -2,7 +2,6 @@
using Fantasy.Async;
using Fantasy.Entitas;
using Fantasy.Network.Interface;
using NB.Map;
namespace NB.Game;
@@ -11,7 +10,7 @@ public class C2Game_GetRoleInfoRequestHandler : RouteRPC<Player, C2Game_GetRoleI
protected override async FTask Run(Player entity, C2Game_GetRoleInfoRequest request,
Game2C_GetRoleInfoResponse response, Action reply)
{
response.RoomCode = "13AHVL";
response.RoomCode = "136A69";
response.RoleInfo = entity.GetRoleInfo();
await FTask.CompletedTask;

View File

@@ -22,6 +22,12 @@ public class C2Game_RigChangeRequestHandler : RouteRPC<Player, C2Game_RigChangeR
return;
}
if (item.InUse)
{
response.ErrorCode = ErrorCode.ErrArgs; //已使用的
return;
}
if (request.IsAdd)
{
//安装配件需要检查配件是否已被使用

View File

@@ -0,0 +1,31 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Network.Interface;
namespace NB.Game;
public class C2Game_UseItemRequestHandler : RouteRPC<Player, C2Game_UseItemRequest, Game2C_UseItemResponse>
{
protected override async FTask Run(Player entity, C2Game_UseItemRequest request, Game2C_UseItemResponse response,
Action reply)
{
var itemContainer = entity.GetComponent<PlayerItemContainerComponent>();
if (itemContainer == null)
{
response.ErrorCode = ErrorCode.ErrArgs;
return;
}
if (!itemContainer.Items.TryGetValue(request.ItemId, out var item))
{
response.ErrorCode = ErrorCode.ErrArgs;
return;
}
var itemType = ItemHelper.GetType(item.ConfigId);
if (itemType == ItemBasicType.Rod)
{
//鱼竿
}
}
}

View File

@@ -1,6 +1,5 @@
using Fantasy;
using Fantasy.Entitas;
using NB.Map;
namespace NB.Game;

View File

@@ -4,17 +4,22 @@ public static class ItemHelper
{
public static ItemBasicType GetType(uint id)
{
var type = (int)(id / 10000);
if (type == 1)
{
return ItemBasicType.Currency;
}
if (type == 21)
{
return ItemBasicType.Fish;
}
return ItemBasicType.Item;
return (ItemBasicType)(id / 10000);
}
// public static ItemBasicType GetType(uint id)
// {
// var type = (int)(id / 10000);
// if (type == 1)
// {
// return ItemBasicType.Currency;
// }
//
// if (type == 21)
// {
// return ItemBasicType.Fish;
// }
//
// return ItemBasicType.Item;
// }
}

View File

@@ -18,6 +18,9 @@ public class ItemDestroySystem : DestroySystem<Item>
public static class ItemSystem
{
public static ItemInfo ToItemInfo(this Item self)
{
return new ItemInfo()

View File

@@ -0,0 +1,49 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Entitas;
using Fantasy.Network.Interface;
namespace NB.Game;
public class C2Map_CreateRoomRequestHandler : RouteRPC<Player, C2Map_CreateRoomRequest, Map2C_CreateRoomResponse>
{
protected override async FTask Run(Player entity, C2Map_CreateRoomRequest request,
Map2C_CreateRoomResponse response,
Action reply)
{
var mapUnit = entity.GetComponent<MapUnitComponent>();
if (mapUnit == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
if (mapUnit.MapId != request.MapId)
{
response.ErrorCode = ErrorCode.MapCreateRoomNotEnter;
return;
}
var roomManageComponent = entity.Scene.GetComponent<RoomManageComponent>();
if (roomManageComponent == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var room = roomManageComponent.Create(entity.Id);
if (room == null)
{
response.ErrorCode = ErrorCode.MapCreateRoomMax;
return;
}
Log.Info(
$"创建房间=== sId={entity.Scene.SceneConfigId} map:{request.MapId} id={room.RoomId} code={room.Code}");
response.RoomCode = room.Code;
await FTask.CompletedTask;
}
}

View File

@@ -0,0 +1,45 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Network.Interface;
namespace NB.Game;
public class C2Map_LookHandler : Route<Player, C2Map_Look>
{
protected override async FTask Run(Player entity, C2Map_Look message)
{
var mapUnit = entity.GetComponent<MapUnitComponent>();
if (mapUnit == null)
{
// response.ErrorCode = ErrorCode.ErrServer;
return;
}
var roomId = mapUnit.RoomId;
var roomManageComponent = entity.Scene.GetComponent<RoomManageComponent>();
var room = roomManageComponent.Get(roomId);
if (room == null)
{
return;
}
var notifyMessage = new Map2C_LookeNotify()
{
Id = entity.Id,
Rotation = message.Rotation,
Timestamp = message.Timestamp
};
// entity.Rotation.x = message.Rotation.x;
// entity.Rotation.y = message.Rotation.y;
// entity.Rotation.z = message.Rotation.z;
foreach (var (_, unit) in room.Units)
{
// if (unit.Id == entity.Id) continue;
entity.Scene.NetworkMessagingComponent.SendInnerRoute(unit.SessionRunTimeId, notifyMessage);
}
await FTask.CompletedTask;
}
}

View File

@@ -0,0 +1,54 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Helper;
using Fantasy.Network.Interface;
namespace NB.Game;
public class C2Map_MoveHandler : Route<Player, C2Map_Move>
{
protected override async FTask Run(Player entity, C2Map_Move message)
{
var mapUnit = entity.GetComponent<MapUnitComponent>();
if (mapUnit == null)
{
// response.ErrorCode = ErrorCode.ErrServer;
return;
}
var roomManageComponent = entity.Scene.GetComponent<RoomManageComponent>();
var roomId = mapUnit.RoomId;
var room = roomManageComponent.Get(roomId);
if (room == null)
{
return;
}
// var mapUnitManageComponent = entity.Scene.GetComponent<MapUnitManageComponent>();
var notifyMessage = new Map2C_MoveNotify()
{
Id = entity.Id,
Position = message.Position,
Rotation = message.Rotation,
IsStop = message.IsStop,
Direction = message.Direction,
Timestamp = TimeHelper.Now
};
// entity.Position.x = message.Position.x;
// entity.Position.y = message.Position.y;
// entity.Position.z = message.Position.z;
//
// entity.Rotation.x = message.Rotation.x;
// entity.Rotation.y = message.Rotation.y;
// entity.Rotation.z = message.Rotation.z;
foreach (var (_, unit) in room.Units)
{
// if (unit.Id == entity.Id) continue;
entity.Scene.NetworkMessagingComponent.SendInnerRoute(unit.SessionRunTimeId, notifyMessage);
}
await FTask.CompletedTask;
}
}

View File

@@ -0,0 +1,41 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Network.Interface;
namespace NB.Game;
public class C2Map_RolePropertyChangeHandler : Route<Player, C2Map_RolePropertyChange>
{
protected override async FTask Run(Player entity, C2Map_RolePropertyChange message)
{
var mapUnit = entity.GetComponent<MapUnitComponent>();
if (mapUnit == null)
{
// response.ErrorCode = ErrorCode.ErrServer;
return;
}
var roomManageComponent = entity.Scene.GetComponent<RoomManageComponent>();
var roomId = mapUnit.RoomId;
var room = roomManageComponent.Get(roomId);
if (room == null)
{
return;
}
var notifyMessage = new Map2C_RolePropertyChangeNotify()
{
Id = entity.Id,
Propertys = message.Propertys,
};
foreach (var (_, unit) in room.Units)
{
if (unit.Id == entity.Id) continue;
entity.Scene.NetworkMessagingComponent.SendInnerRoute(unit.SessionRunTimeId, notifyMessage);
}
await FTask.CompletedTask;
}
}

View File

@@ -0,0 +1,60 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Network.Interface;
namespace NB.Game;
public class C2Map_TakeItemRequestHandler : RouteRPC<Player, C2Map_TakeItemRequest, Map2C_TakeItemResponse>
{
protected override async FTask Run(Player entity, C2Map_TakeItemRequest request, Map2C_TakeItemResponse response,
Action reply)
{
var itemContainer = entity.GetComponent<PlayerItemContainerComponent>();
if (itemContainer == null)
{
response.ErrorCode = ErrorCode.ErrArgs;
return;
}
if (!itemContainer.Items.TryGetValue(request.Id, out var item))
{
response.ErrorCode = ErrorCode.ErrArgs;
return;
}
var mapUnit = entity.GetComponent<MapUnitComponent>();
if (mapUnit == null)
{
response.ErrorCode = ErrorCode.ErrArgs;
return;
}
var itemType = ItemHelper.GetType(item.ConfigId);
if (itemType == ItemBasicType.Rod)
{
itemContainer.Binding.TryGetValue(item.Id, out var itemRod);
//鱼竿
var itemGear = mapUnit.GetOrAddItemGear(item);
if (itemRod != null)
{
itemGear.Rings.AddRange(itemRod);
}
}
var roomManageComponent = entity.Scene.GetComponent<RoomManageComponent>();
var roomId = mapUnit.RoomId;
var room = roomManageComponent.Get(roomId);
if (room != null)
{
var notifyMessage = new Map2C_RoleGearChangeNotify();
// notifyMessage
// return;
foreach (var (_, unit) in room.Units)
{
// if (unit.Id == entity.Id) continue;
entity.Scene.NetworkMessagingComponent.SendInnerRoute(unit.SessionRunTimeId, notifyMessage);
}
}
}
}

View File

@@ -0,0 +1,83 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Network.Interface;
using NB.Game;
namespace NB.Game.Inner;
/// <summary>
/// 请求进入地图
/// </summary>
public class G2Map_EnterMapRequestHandler : RouteRPC<Scene, G2Map_EnterMapRequest, Map2G_EnterMapResponse>
{
protected override async FTask Run(Scene entity, G2Map_EnterMapRequest request, Map2G_EnterMapResponse response,
Action reply)
{
var roomManageComponent = entity.GetComponent<RoomManageComponent>();
if (roomManageComponent == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var mapUnitManage = entity.GetComponent<PlayerManageComponent>();
if (mapUnitManage == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var player = mapUnitManage.Get(request.AccountId);
if (player == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var mapUnit = player.GetComponent<MapUnitComponent>();
if (mapUnit == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
//进入地图
var mapManageComponent = entity.GetComponent<MapManageComponent>();
var map = mapManageComponent.Get(request.MapId);
if (map == null)
{
response.ErrorCode = ErrorCode.MapIdError;
return;
}
mapUnit.MapId = request.MapId;
// 如果没有房间代码,则只是进入地图,直接返回,不执行后续逻辑
if (string.IsNullOrEmpty(request.RoomCode))
{
response.Units = [player.ToMapUnitInfo()];
return;
}
RoomHelper.ParseCode(request.RoomCode, out var serviceId, out var roomId);
if (serviceId < 1 || roomId < 1)
{
return;
}
var room = roomManageComponent.Get(roomId);
if (room == null)
{
return;
}
response.ErrorCode = await room.Enter(player);
response.RoomCode = room.Code;
if (response.ErrorCode == ErrorCode.Successful)
{
mapUnit.RoomId = room.RoomId;
response.Units = room.ToMapUnitInfo();
}
}
}

View File

@@ -0,0 +1,51 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Network.Interface;
namespace NB.Game.Inner;
public class G2Map_ExitRoomRequestHandler : RouteRPC<Scene, G2Map_ExitRoomRequest, Map2G_ExiRoomResponse>
{
protected override async FTask Run(Scene entity, G2Map_ExitRoomRequest request, Map2G_ExiRoomResponse response,
Action reply)
{
var roomManageComponent = entity.GetComponent<RoomManageComponent>();
if (roomManageComponent == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var mapUnitManage = entity.GetComponent<PlayerManageComponent>();
if (mapUnitManage == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var player = mapUnitManage.Get(request.AccountId);
if (player == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var mapUnit = player.GetComponent<MapUnitComponent>();
if (mapUnit == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
var room = roomManageComponent.Get(mapUnit.RoomId);
if (room == null)
{
response.ErrorCode = ErrorCode.ErrServer;
return;
}
player.RemoveComponent<MapUnitComponent>();
response.ErrorCode = await room.Enter(player);
// room.Units.Remove(mapUnit.Id);
}
}

View File

@@ -0,0 +1,20 @@
using Fantasy;
using Fantasy.Entitas;
namespace NB.Game;
public class MapFactory
{
/// <summary>
/// 创建一个地图
/// </summary>
/// <param name="scene"></param>
/// <param name="mapId"></param>
/// <returns></returns>
public static Map? Create(Scene scene, int mapId)
{
var map = Entity.Create<Map>(scene, true, true);
map.MapId = mapId;
return map;
}
}

View File

@@ -0,0 +1,68 @@
using System.Text;
namespace NB.Game;
public static class RoomHelper
{
#region id
private const string Base36Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private const int RoomSeqBits = 16; // 每个服务最多 65535 个房间
/// <summary>
/// 生成房间码固定5位
/// </summary>
/// <param name="serviceId"></param>
/// <param name="roomSeq"></param>
/// <returns></returns>
public static string GenerateCode(uint serviceId, int roomSeq)
{
long packed = ((long)serviceId << RoomSeqBits) | (uint)roomSeq;
string code = EncodeBase36(packed);
// 固定5位不够左侧补0
return code.PadLeft(5, '0');
}
/// <summary>
/// 解析房间码
/// </summary>
/// <param name="code"></param>
/// <param name="serviceId"></param>
/// <param name="roomSeq"></param>
public static void ParseCode(string code, out uint serviceId, out int roomSeq)
{
long packed = DecodeBase36(code);
roomSeq = (int)(packed & ((1 << RoomSeqBits) - 1));
serviceId = (uint)(packed >> RoomSeqBits);
}
private static string EncodeBase36(long value)
{
if (value == 0) return "0";
StringBuilder sb = new StringBuilder();
while (value > 0)
{
int remainder = (int)(value % 36);
sb.Insert(0, Base36Chars[remainder]);
value /= 36;
}
return sb.ToString();
}
private static long DecodeBase36(string str)
{
long result = 0;
foreach (char c in str)
{
int val = Base36Chars.IndexOf(c);
if (val < 0) throw new ArgumentException("Invalid Base36 character: " + c);
result = result * 36 + val;
}
return result;
}
#endregion
}

View File

@@ -0,0 +1,61 @@
using Fantasy.Entitas;
using Fantasy.Entitas.Interface;
namespace NB.Game;
public class MapManageComponentDestroySystem : DestroySystem<MapManageComponent>
{
protected override void Destroy(MapManageComponent self)
{
foreach (var (_, map) in self.Maps)
{
map.Dispose();
}
self.Maps.Clear();
}
}
public class MapManageComponentAwakeSystem : AwakeSystem<MapManageComponent>
{
protected override void Awake(MapManageComponent self)
{
//初始化所有地图
for (int i = 1; i < 100; i++)
{
//初始化100个地图
var map = MapFactory.Create(self.Scene, i);
if (map != null)
{
self.Add(map);
}
}
}
}
public static class MapManageComponentSystem
{
#region
public static void Add(this MapManageComponent self, Map map)
{
self.Maps[map.MapId] = map;
}
public static bool Remove(this MapManageComponent self, int mapId)
{
if (self.Maps.TryGetValue(mapId, out var map))
{
map.Dispose();
}
return true;
}
public static Map? Get(this MapManageComponent self, int mapId)
{
return self.Maps.GetValueOrDefault(mapId);
}
#endregion
}

View File

@@ -0,0 +1,57 @@
using Fantasy;
using Fantasy.Async;
using Fantasy.Entitas.Interface;
namespace NB.Game;
public class MapRoomDestroySystem : DestroySystem<MapRoom>
{
protected override void Destroy(MapRoom self)
{
self.Map = 0;
self.Password = string.Empty;
self.CreateTime = 0;
self.Owner = 0;
self.Units.Clear();
}
}
public static class MapRoomSystem
{
public static async FTask<uint> Enter(this MapRoom self, Player unit)
{
self.Units.TryAdd(unit.Id, unit);
// var notifyMessage = new Map2C_RoleEnterRoomNotify()
// {
// Info = unit.ToMapUnitInfo(),
// };
//
// foreach (var (_, roomUnit) in self.Units)
// {
// // if (roomUnit.Id == unit.Id) continue;
// // 同步其他客户端
// self.Scene.NetworkMessagingComponent.SendInnerRoute(roomUnit.GateRouteId, notifyMessage);
// }
await FTask.CompletedTask;
return ErrorCode.Successful;
}
public static async FTask Exit(this MapRoom self, long id)
{
self.Units.Remove(id);
await FTask.CompletedTask;
}
public static List<MapUnitInfo> ToMapUnitInfo(this MapRoom self)
{
List<MapUnitInfo> ret = new List<MapUnitInfo>();
foreach (var (_, unit) in self.Units)
{
ret.Add(unit.ToMapUnitInfo());
}
return ret;
}
}

View File

@@ -0,0 +1,16 @@
using Fantasy.Entitas.Interface;
namespace NB.Game;
public class MapDestroySystem : DestroySystem<Map>
{
protected override void Destroy(Map self)
{
self.MapId = 0;
self.Units.Clear();
}
}
public static class MapSystem
{
}

View File

@@ -0,0 +1,31 @@
using Fantasy;
using Fantasy.Async;
namespace NB.Game;
public static class MapUnitComponentSystem
{
public static MapUnitGear GetOrAddItemGear(this MapUnitComponent self, Item item)
{
var mapItem = self.Gears.Find(t => t.Item == item.Id);
if (mapItem == null)
{
mapItem = new MapUnitGear();
mapItem.Item = item.Id;
self.Gears.Add(mapItem);
}
return mapItem;
}
public static List<GearInfo> ToMapUnitInfo(this MapUnitComponent self)
{
List<GearInfo> ret = new List<GearInfo>();
// foreach (var (_, unit) in self.Units)
// {
// // ret.Add(unit.ToMapUnitInfo());
// }
return ret;
}
}

View File

@@ -0,0 +1,122 @@
using Fantasy;
using Fantasy.Entitas;
using Fantasy.Entitas.Interface;
namespace NB.Game;
public class RoomManageComponentAwakeSystem : AwakeSystem<RoomManageComponent>
{
protected override void Awake(RoomManageComponent self)
{
for (int i = 1; i <= 65535; i++)
{
self.FreeIds.Enqueue(i, i);
}
}
}
public class RoomManageComponentDestroySystem : DestroySystem<RoomManageComponent>
{
protected override void Destroy(RoomManageComponent self)
{
foreach (var (_, room) in self.Rooms)
{
room.Dispose();
}
self.Rooms.Clear();
}
}
public static class RoomManageComponentSystem
{
#region
public static MapRoom? Create(this RoomManageComponent self, long ownerId)
{
var roomId = self.AllocateId();
if (roomId < 1)
{
return null;
}
// roomManageComponent.on
var room = Entity.Create<MapRoom>(self.Scene, true, true);
room.Owner = ownerId;
room.RoomId = roomId;
room.Code = RoomHelper.GenerateCode(self.Scene.SceneConfigId, roomId);
self.Add(room);
return room;
}
public static void Add(this RoomManageComponent self, MapRoom room)
{
self.Rooms[room.RoomId] = room;
}
public static bool Remove(this RoomManageComponent self, int roomId)
{
if (self.Rooms.TryGetValue(roomId, out var room))
{
self.ReleaseId(room.RoomId);
room.Dispose();
}
return true;
}
public static void Check(this RoomManageComponent self, int roomId)
{
if (self.Rooms.TryGetValue(roomId, out var room))
{
if (room.Units.Count < 1)
{
Log.Info($"房间没人了解散房间id={roomId}");
// self.Remove(roomId);
}
}
}
public static MapRoom? Get(this RoomManageComponent self, int roomId)
{
return self.Rooms.GetValueOrDefault(roomId);
}
// public static MapRoom? Get(this RoomManageComponent self, long roomId)
// {
// return self.Rooms.GetValueOrDefault(roomId);
// }
#endregion
#region Id
/// <summary>
/// 分配一个新的房间ID
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static int AllocateId(this RoomManageComponent self)
{
if (self.FreeIds.Count == 0) return 0;
int id = self.FreeIds.Dequeue();
self.InUseID.Add(id);
return id;
}
/// <summary>
/// 释放房间ID
/// </summary>
/// <param name="self"></param>
/// <param name="id"></param>
public static void ReleaseId(this RoomManageComponent self, int id)
{
if (self.InUseID.Remove(id))
{
self.FreeIds.Enqueue(id, id);
}
}
#endregion
}

View File

@@ -62,6 +62,7 @@ public static class PlayerManageComponentSystem
await account.TryComponent<PlayerItemContainerComponent>();
await account.TryComponent<PlayerWalletComponent>();
await account.TryComponent<FishContainer>();
account.GetOrAddComponent<MapUnitComponent>();
if (needInit)
{

View File

@@ -63,45 +63,26 @@ public static class PlayerSystem
}
#endregion
#region
public static void SetTestData(this Player player)
public static MapUnitInfo ToMapUnitInfo(this Player self)
{
var ret = new MapUnitInfo()
{
Id = self.Id,
Position = Vector3Info.Create(self.Scene),
Rotation = Vector3Info.Create(self.Scene),
};
// Dictionary<int, List<int>> rigDic = new Dictionary<int, List<int>>()
// {
// { 30001, [50001, 60001, 70002, 90001, 100001] },
// { 30002, [40001, 50001, 60001, 70002, 00001, 100001] },
// { 30003, [40001, 60001, 80001] }
// };
//
// var itemContainer = player.GetComponent<PlayerItemContainerComponent>();
//
// //添加测试数据
// if (itemContainer != null && itemContainer.FishingRig.Count < 1)
// {
// foreach (var (rod, list) in rigDic)
// {
// if (itemContainer.GetFistItemByConfigId(rod, out var item) && item != null)
// {
// var childs = new List<long>();
// foreach (var i in list)
// {
// if (itemContainer.GetFistItemByConfigId(i, out var itemChild) && itemChild != null)
// {
// childs.Add(itemChild.Id);
// }
// }
//
// itemContainer.FishingRig[item.Id] = childs;
// }
// }
//
// itemContainer.Save();
// }
var mapUnit = self.GetComponent<MapUnitComponent>();
ret.Position.x = mapUnit.Position.x;
ret.Position.y = mapUnit.Position.y;
ret.Position.z = mapUnit.Position.z;
ret.Rotation.x = mapUnit.Rotation.x;
ret.Rotation.y = mapUnit.Rotation.y;
ret.Rotation.z = mapUnit.Rotation.z;
return ret;
}
#endregion
}