This commit is contained in:
CortexCore 2024-11-23 17:20:13 +08:00
commit bb257507bc
133 changed files with 2574 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# custom
.idea
.plastic
.vscode
/Assets/StreamingAssets/yoo
yoo/
Bundles/
Profiler/
/bin
/obj

23
Com.Project.B.csproj Normal file
View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\BITKit\BITKit.csproj" />
</ItemGroup>
<ItemGroup>
<!-- 排除Unity文件 -->
<None Remove="**\*.meta"/>
<None Remove="**\*.asmdef"/>
</ItemGroup>
<ItemGroup>
<Reference Include="Unity.Mathematics">
<HintPath>..\BITKit\DLL\Unity.Mathematics.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

8
Src/Authorize.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5df31814c76fd5f429ae3f4c7b60aeaf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
{
"name": "Com.Project.B.Authorize",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 213fef69b5745f547bdcc386328dc311
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
using System;
namespace Com.Project.B.Authorize
{
/// <summary>
/// 授权数据
/// </summary>
public interface IAuthorizeData
{
/// <summary>
/// 链接ID,仅用于网络通讯
/// </summary>
int ConnectionId { get; set; }
/// <summary>
/// 玩家ID
/// </summary>
Guid PlayerId { get; }
/// <summary>
/// 授权令牌
/// </summary>
string Token { get; }
/// <summary>
/// 上次更新时间
/// </summary>
DateTime LastUpdateTime { get; }
}
public struct AuthorizeData:IAuthorizeData
{
public int ConnectionId { get; set; }
public Guid PlayerId { get; set; }
public string Token { get; set; }
public DateTime LastUpdateTime { get; set; }
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 64fdf8c4f6b4457c87647acd79359508
timeCreated: 1724414639

View File

@ -0,0 +1,43 @@
using System;
using Com.Project.B.Authorize;
using Cysharp.Threading.Tasks;
namespace Project.B.Authorize
{
/// <summary>
/// 授权服务
/// </summary>
public interface IAuthorizeService
{
/// <summary>
/// 尝试获取授权数据
/// </summary>
/// <param name="playerId"></param>
/// <param name="data"></param>
/// <returns></returns>
bool TryGetAuthorizeData(Guid playerId, out IAuthorizeData data);
UniTask<IAuthorizeData[]> GetAllAuthorizeDataAsync();
/// <summary>
/// 授权和登录
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
UniTask<IAuthorizeData> AuthorizeAsync(IAuthorizeData data);
/// <summary>
/// 保持心跳,超时则断开链接
/// </summary>
/// <param name="playerId"></param>
/// <param name="connectionId"></param>
/// <returns></returns>
UniTask<bool> HeartbeatAsync(Guid playerId,int connectionId);
/// <summary>
/// 授权成功回调
/// </summary>
event Action<IAuthorizeData> OnAuthorized;
/// <summary>
/// 授权超时回调
/// </summary>
event Action<IAuthorizeData> OnAuthorizeTimeout;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d55accd2aeb80c940a0b80fcd1e4c634
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: af56161a7c158cb4f97da44de0d64528
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
{
"name": "Com.Project.B.CharacterAnimation",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:ecc5a2501a2c44d4cb8366674714f3d9",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:d8b63aba1907145bea998dd612889d6b"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6bf9bfd639affa44788ad1d79942746b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace Project.B.Animation
{
public interface IAnimationFactory
{
public UniTask InitializeAsync();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93300d0073822a34184faa323300fcfd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using BITKit;
using Unity.Mathematics;
namespace Project.B.Animation
{
public interface IHumanoidAnimationFactory: IAnimationFactory
{
IWrapper<float2> CreateIdleAnimation();
IWrapper<float2> CreateWalkAnimation();
IWrapper<float2> CreateCrouchedAnimation();
IWrapper<float2> CreateInAirAnimation();
IWrapper<float> CreateRunAnimation();
IWrapper<float> CreateSprintAnimation();
IWrapper<float2> CreateKnockedAnimation();
object CreateKnockingAnimation();
object CreateDeathAnimation();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85e6ac8c46e30404cbd8d8cffc15f319
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using BITKit;
using Unity.Mathematics;
namespace Project.B.Animation
{
public interface IPlayerAnimationFactory : IHumanoidAnimationFactory
{
public object CreateStepUpAnimation();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f0cf21fa72c864844acd31f144d12f86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0b88cd3c8eae9724caabbf566ba0e879
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
{
"name": "Com.Project.B.CharacterController",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:d8b63aba1907145bea998dd612889d6b"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ecc5a2501a2c44d4cb8366674714f3d9
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
namespace Project.B.CharacterController
{
public interface IBotCharacterController
{
ICharacterController CharacterController { get; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9ed442d9b01567644b3ba71d2290f15d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
using BITKit.StateMachine;
using Unity.Mathematics;
namespace Project.B.CharacterController
{
/// <summary>
/// 角色控制器
/// </summary>
public interface ICharacterController:IStateMachine<ICharacterState>
{
float3 Center { get; }
float3 Position { get; set; }
float3 Velocity { get; set; }
float3 AngularVelocity { get; }
quaternion Rotation { get; set; }
float3 SelfVelocity { get; set; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea09f811bb3610f448df064bf4af3c3b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Project.B.CharacterController
{
/// <summary>
/// 角色服务
/// </summary>
public interface ICharacterService
{
IDictionary<int, ICharacterController> Dictionary { get; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8623eebfb2e93db44b3c1f3356660112
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,73 @@
using BITKit.StateMachine;
using Unity.Mathematics;
namespace Project.B.CharacterController
{
/// <summary>
/// 角色状态
/// </summary>
public interface ICharacterState : IState
{
public void UpdateVelocity(ref float3 currentVelocity, float deltaTime);
public void UpdateRotation(ref float3 localPosition, ref quaternion currentRotation,
ref quaternion viewRotation, float deltaTime);
public void BeforeUpdateVelocity(float deltaTime);
public void AfterUpdateVelocity(float deltaTime);
}
/// <summary>
/// 角色状态数据
/// </summary>
public interface ICharacterStateData
{
public float BaseHeight { get; }
public float BaseSpeed { get; }
public float2 ViewOffset { get; }
}
/// <summary>
/// 空状态
/// </summary>
public interface ICharacterStateEmpty:ICharacterState{}
/// <summary>
/// 静止
/// </summary>
public interface ICharacterStateIdle:ICharacterState{}
/// <summary>
/// 行走
/// </summary>
public interface ICharacterStateWalk:ICharacterState{}
/// <summary>
/// 蹲下
/// </summary>
public interface ICharacterStateCrouched:ICharacterState{}
/// <summary>
/// 奔跑
/// </summary>
public interface ICharacterStateRun:ICharacterState{}
/// <summary>
/// 战术跑
/// </summary>
public interface ICharacterSprint:ICharacterState{}
/// <summary>
/// 在空中,包括跳跃、下落、飞行等
/// </summary>
public interface ICharacterStateInAir:ICharacterState{}
/// <summary>
/// 爬上低障碍物
/// </summary>
public interface ICharacterStateStepUp:ICharacterState{}
/// <summary>
/// 翻阅障碍物
/// </summary>
public interface ICharacterStateVault:ICharacterState{}
/// <summary>
/// 攀爬
/// </summary>
public interface ICharacterStateClimb:ICharacterState{}
/// <summary>
/// 被击倒
/// </summary>
public interface ICharacterKnocked:ICharacterState{}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a1d7bf82adaa85429d4edf3663803b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using BITKit;
using Unity.Mathematics;
namespace Project.B.CharacterController
{
public interface IPlayerCharacterController
{
ICharacterController CharacterController { get; }
IDictionary<int,quaternion> AdditiveCameraQuaternion { get; }
IDictionary<int,float> ZoomFactor { get; }
ValidHandle AllowTpsCamera { get; }
ValidHandle AllowRun { get; }
ValidHandle AllowSprint { get; }
void CancelRun();
void CancelSprint();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1653b18508ad4d749bcea633bff67802
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Src/Dialogue.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ee183f11afcda5644bd64299bd2f47f8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,79 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Net.Project.B.Dialogue
{
/// <summary>
/// 对话数据
/// </summary>
public interface IDialogueData
{
/// <summary>
/// 唯一对话ID
/// </summary>
public int Identity { get; set; }
/// <summary>
/// 通道ID,用于区分不同的对话
/// </summary>
public int Channel { get; }
/// <summary>
/// 演员ID,谁是说话的人
/// </summary>
public int ActorIdentity { get; }
/// <summary>
/// 文本
/// </summary>
public string Text { get; }
/// <summary>
/// 语音路径
/// </summary>
public string VoicePath { get; }
/// <summary>
/// 等待对话完成
/// </summary>
/// <returns></returns>
TaskAwaiter GetAwaiter();
}
/// <summary>
/// 对话选择
/// </summary>
public interface IDialogueChoice
{
/// <summary>
/// 索引
/// </summary>
public int Index { get; }
/// <summary>
/// 文本
/// </summary>
public string Text { get; }
/// <summary>
/// 是否可选
/// </summary>
public bool Enabled { get; }
/// <summary>
/// 备注,例如:选择这个选项会触发什么事件,不可选的原因等
/// </summary>
public string Remark { get; }
}
public struct DialogueData:IDialogueData
{
public int Identity { get; set; }
public int Channel { get; set; }
public int ActorIdentity { get; set; }
public string Text { get; set; }
public string VoicePath { get; set; }
public TaskAwaiter GetAwaiter()
{
throw new System.NotImplementedException();
}
}
public struct DialogueChoice:IDialogueChoice
{
public int Index { get; set; }
public string Text { get; set; }
public bool Enabled { get; set; }
public string Remark { get; set; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ebb9eb40cce574a44b3419bd4d58411f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,91 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using BITKit;
using Cysharp.Threading.Tasks;
namespace Net.Project.B.Dialogue
{
/// <summary>
/// 对话服务
/// </summary>
public interface IDialogueService
{
/// <summary>
/// 所有对话
/// </summary>
IReadOnlyDictionary<int, IDialogueData> Dialogues { get; }
/// <summary>
/// 对话开始
/// </summary>
public event Func<IDialogueData, UniTask> OnDialogueStart;
/// <summary>
/// 对话结束
/// </summary>
public event Action<IDialogueData> OnDialogueEnd;
/// <summary>
/// 对话选择
/// </summary>
public event Func<IDialogueData, IReadOnlyCollection<IDialogueChoice>, UniTask<int>> OnDialogueChoose;
/// <summary>
/// 对话选择回调
/// </summary>
public event Action<IDialogueData, IDialogueChoice> OnDialogueChose;
/// <summary>
/// 开启对话
/// </summary>
/// <param name="dialogueData">对话</param>
/// <returns></returns>
UniTask CreateDialogue(IDialogueData dialogueData);
UniTask<int> CreateDialogue(IDialogueData dialogueData, IReadOnlyCollection<IDialogueChoice> dialogueChoices);
}
public class DialogueService : IDialogueService
{
public IReadOnlyDictionary<int, IDialogueData> Dialogues => _dialogues;
public event Func<IDialogueData, UniTask> OnDialogueStart;
public event Action<IDialogueData> OnDialogueEnd;
public event Func<IDialogueData, IReadOnlyCollection<IDialogueChoice>, UniTask<int>> OnDialogueChoose;
public event Action<IDialogueData, IDialogueChoice> OnDialogueChose;
public async UniTask CreateDialogue(IDialogueData dialogueData)
{
if (_dialogues.TryAdd(dialogueData.Identity, dialogueData) is false)
{
dialogueData.Identity = _dialogues.Keys.Max() + 1;
_dialogues.TryAdd(dialogueData.Identity, dialogueData);
}
await OnDialogueStart.UniTaskFunc(dialogueData);
OnDialogueEnd?.Invoke(dialogueData);
}
public async UniTask<int> CreateDialogue(IDialogueData dialogueData,
IReadOnlyCollection<IDialogueChoice> dialogueChoices)
{
if (OnDialogueChoose is null)
{
throw new NullReferenceException("OnDialogueChoose is null,unable to create dialogue");
}
var task = OnDialogueChoose.Invoke(dialogueData, dialogueChoices);
var index = await task;
OnDialogueChose?.Invoke(dialogueData, dialogueChoices.ElementAt(index));
return index;
}
private readonly ConcurrentDictionary<int, IDialogueData> _dialogues = new();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4b6700c7171a00048b0d5907bd7c0133
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
{
"name": "Net.Project.B.Dialogue",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ba8323a5a01afc24188ded7f4b05db8a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Src/Entities.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 035b607824c8f7444a065771731609f5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
{
"name": "Com.Project.B.Entities",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c469c0b0902774247810f42d61a18bd7
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using BITKit.Entities;
using Cysharp.Threading.Tasks;
namespace Project.B.Entities
{
/// <summary>
/// 实体工厂
/// </summary>
public interface IEntitiesFactory:IDisposable
{
IReadOnlyDictionary<int,IEntity> Entities { get; }
UniTask<IEntity> CreateAsync(string addressablePath);
public event Func<string, IEntity,UniTask> OnEntityCreate;
public event Func<string, IEntity,UniTask> OnEntityCreated;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a04dc5a4e09c045449fae446e3ce4f4c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,11 @@
namespace Project.B.Entities
{
/// <summary>
/// 游戏实体服务,通常是场景中的角色,怪物,道具等
/// </summary>
public interface IInGameEntitiesService
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 37fcf1ccb8b19e049a5e20b3ceaf53de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
namespace Project.B.Entities
{
public interface INpcFactory:IEntitiesFactory
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 15be9f6a652c2fa4da9f3a5432cea177
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
namespace Project.B.Entities
{
/// <summary>
/// 玩家工厂
/// </summary>
public interface IPlayerFactory:IEntitiesFactory
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 40f616061eb458a4c9ac203fe981a405
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Src/GameService.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e61e9d1af77a0a3459eb82460e214bbd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
{
"name": "Com.Project.B.GameService",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:a4033552c5c40fa408838a1ce2b1b215",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 12c795c5ebfb7b245a0399e28b4015e8
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,58 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BITKit;
using Cysharp.Threading.Tasks;
namespace Project.B.Map
{
/// <summary>
/// 游戏地图服务
/// </summary>
public interface IGameMapService
{
/// <summary>
/// 初始化状态
/// </summary>
InitializationState InitializationState { get; }
/// <summary>
/// 当前已加载或正在加载的地图
/// </summary>
string CurrentMap { get; }
/// <summary>
/// 获取地图
/// </summary>
/// <returns></returns>
UniTask<string> GetMapAsync();
/// <summary>
/// 进入地图
/// </summary>
/// <param name="map"></param>
/// <returns></returns>
UniTask StartMapAsync(string map);
/// <summary>
/// 停止地图,也是返回菜单的意思
/// </summary>
/// <returns></returns>
UniTask StopMapAsync();
/// <summary>
/// 当加载状态发生变化时
/// </summary>
event Action<InitializationState> OnInitializationStateChanged;
/// <summary>
/// 切换场景前
/// </summary>
event Func<string, UniTask> OnMapChanging;
/// <summary>
/// 切换场景后
/// </summary>
event Action<Guid,string> OnMapChanged;
/// <summary>
/// 地图加载进度
/// </summary>
event Action<Guid,float,string> OnMapLoadingProgress;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3cef42cfdedec0c41b3992402685c70c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Src/Health.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 62c1efeb1f5e26c45b753b1b37c1e3f7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,89 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using BITKit;
using Cysharp.Threading.Tasks;
namespace Net.Project.B.Health
{
/// <summary>
/// 生命值服务
/// </summary>
public interface IHealthService
{
/// <summary>
/// 已缓存的生命值
/// </summary>
public IReadOnlyDictionary<int,int> Healths { get; }
/// <summary>
/// 在改变生命值前,ID,当前生命值,新的生命值,来源
/// <returns>增加的数值</returns>
/// </summary>
public event Func<int,int,int,object,int> OnHealthPlus;
/// <summary>
/// 在改变生命值后
/// </summary>
/// /// <summary>
/// 当健康值发生变化时触发的事件。
/// </summary>
public event Action<int,int,int,object> OnHealthChanged;
/// <summary>
/// 调整生命值
/// </summary>
/// <param name="id"></param>
/// <param name="value">+- not set</param>
/// <returns></returns>
public UniTask<int> AddHealth(int id,int value,object arg);
}
public class HealthService:IHealthService
{
private static HealthService _singleton;
public HealthService()
{
_singleton = this;
}
[BITCommand]
public static void SetHealth(int id, int newHealth)
{
Healths.GetOrAdd(id,100);
Healths.Set(id,newHealth);
OnHealthChanged?.Invoke(id,newHealth,newHealth,null);
}
[BITCommand]
public static void AddHealth(int id, int newHealth)
{
Healths.GetOrAdd(id,100);
_singleton.AddHealth(id, newHealth, null).Forget();
}
IReadOnlyDictionary<int, int> IHealthService.Healths => Healths;
private static event Func<int,int,int,object,int> OnHealthChange;
private static event Action<int,int,int,object> OnHealthChanged;
private static readonly ConcurrentDictionary<int, int> Healths = new();
event Func<int,int,int,object,int> IHealthService.OnHealthPlus
{
add => OnHealthChange += value;
remove => OnHealthChange -= value;
}
event Action<int,int,int,object> IHealthService.OnHealthChanged
{
add => OnHealthChanged += value;
remove => OnHealthChanged -= value;
}
public UniTask<int> AddHealth(int id, int value,object arg)
{
var current = Healths.GetOrAdd(id,100);
foreach (var func in OnHealthChange.CastAsFunc())
{
value =func.Invoke(id,current, value, arg);
}
var newHp = Math.Clamp(current + value, -1, 100);
Healths.Set(id,newHp);
OnHealthChanged?.Invoke(id,current,newHp,arg);
return UniTask.FromResult(newHp);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 128dfad42ea28ca458121d3ca6b70ffc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,109 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using BITKit;
using Microsoft.Extensions.Logging;
namespace Net.Project.B.Health
{
/// <summary>
/// 击倒服务
/// </summary>
public interface IKnockedService
{
/// <summary>
/// 击倒列表
/// </summary>
public HashSet<int> Knocked { get; }
/// <summary>
/// 击倒生命值
/// </summary>
public IReadOnlyDictionary<int,int> KnockedHealth { get; }
/// <summary>
/// 击倒回调
/// </summary>
public event Action<int, bool> OnKnocked;
/// <summary>
/// 击倒生命值回调
/// </summary>
public event Action<int, int, int> OnKnockedHealthChanged;
}
public class KnockedService : IKnockedService,IDisposable
{
private readonly IHealthService _healthService;
private readonly ILogger<KnockedService> _logger;
public KnockedService(IHealthService healthService, ILogger<KnockedService> logger)
{
_healthService = healthService;
_logger = logger;
_healthService.OnHealthPlus += OnHealthPlus;
_healthService.OnHealthChanged += OnHealthChanged;
}
private int OnHealthPlus(int id, int oldHp, int plus, object sendor)
{
var isKnocked = _knocked.Contains(id);
if (oldHp < 0) return plus;
if ((oldHp + plus) > -1) return plus;
if (plus > 0) return plus;
if (isKnocked)
{
var currentHealth = _knockedHealth.GetOrAdd(id,100);
if (currentHealth + plus > -1)
{
var nextHealth = currentHealth + plus;
_knockedHealth[id] = nextHealth;
_onKnockedHealthChanged?.Invoke(id, currentHealth, nextHealth);
_logger.LogInformation($"Entity {id} 的击倒生命值减少了,剩余{_knockedHealth[id]}");
return 0;
}
_knockedHealth.Set(id,-1);
return plus;
}
_knockedHealth.TryAdd(id, 100);
_knocked.Add(id);
_onKnocked?.Invoke(id, true);
_logger.LogInformation($"Entity {id} 被击倒了");
return 0;
}
private void OnHealthChanged(int arg1, int arg2, int arg3, object arg4)
{
var isKnocked = _knocked.Contains(arg1);
if(isKnocked is false)return;
if (arg3 <= arg2) return;
_knocked.Remove(arg1);
_knockedHealth.TryRemove(arg1,out _);
_onKnocked?.Invoke(arg1, false);
_logger.LogInformation($"Entity {arg1} 自起了");
}
private static readonly HashSet<int> _knocked = new();
private static readonly ConcurrentDictionary<int,int> _knockedHealth = new();
private static event Action<int, bool> _onKnocked;
private static event Action<int, int, int> _onKnockedHealthChanged;
public HashSet<int> Knocked=> _knocked;
public IReadOnlyDictionary<int, int> KnockedHealth => _knockedHealth;
public event Action<int, bool> OnKnocked
{
add => _onKnocked += value;
remove => _onKnocked -= value;
}
public event Action<int, int, int> OnKnockedHealthChanged
{
add => _onKnockedHealthChanged += value;
remove => _onKnockedHealthChanged -= value;
}
public void Dispose()
{
_healthService.OnHealthPlus -= OnHealthPlus;
_healthService.OnHealthChanged -= OnHealthChanged;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1eec6f99cef0ae14ab1593764fad6a50
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
{
"name": "Net.Project.B.Health",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8f79dfa3edfa9514b8f6d7d2f0102ccc
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Src/Interaction.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1bcfe1d2412306a47900a35a4f5ae3e2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
{
"name": "Com.Project.B.Interaction",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e527b3ce3106f974585be5134b6200e9
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Net.Project.B.Interaction
{
public enum WorldInteractionProcess
{
None,
Hover,
Started,
Tap,
Hold,
Performed,
}
/// <summary>
/// 可互动类型
/// </summary>
public interface IWorldInteractable
{
public int Id { get; }
public IWorldInteractable Root { get; }
public IWorldInteractionType InteractionType { get; }
public object WorldObject { get; set; }
}
/// <summary>
/// 世界互动服务
/// </summary>
public interface IWorldInteractionService
{
/// <summary>
/// 注册可互动对象
/// </summary>
/// <param name="interactable"></param>
/// <returns></returns>
public bool Register(IWorldInteractable interactable);
/// <summary>
/// 注销可互动对象
/// </summary>
/// <param name="interactable"></param>
/// <returns></returns>
public bool Unregister(IWorldInteractable interactable);
/// <summary>
/// 尝试获取互动
/// </summary>
/// <param name="id">通常是Collider InstanceId</param>
/// <param name="interactable">可互动对象</param>
/// <returns></returns>
public bool TryGetValue(int id, out IWorldInteractable interactable);
/// <summary>
/// 互动
/// </summary>
/// <param name="sender">互动者</param>
/// <param name="interactable">互动对象</param>
/// <param name="process">过程,例如开始,完成,结束</param>
/// <returns>是否互动成功</returns>
bool Interaction(object sender,IWorldInteractable interactable,WorldInteractionProcess process=WorldInteractionProcess.Performed);
/// <summary>
/// 互动回调
/// </summary>
public event Action<object,IWorldInteractable,WorldInteractionProcess,object> OnInteraction;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a77240fca943a0349904c895ba032c26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
namespace Net.Project.B.Interaction
{
/// <summary>
/// 互动类型
/// </summary>
public interface IWorldInteractionType
{
}
/// <summary>
/// 长按互动
/// </summary>
public interface IWorldHoldingInteraction
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c6a00515bdf235468aa2da01fffde5b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Src/Inventory.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c978c6ae445f49849a7c47d44b60a54e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
{
"name": "Com.Project.B.Inventory",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:677cd05ca06c46b4395470200b1acdad",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4f0d7989fc8bc01489c1e1f65eedd1c3
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,36 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BITKit;
namespace Net.Project.B.Inventory
{
/// <summary>
/// 玩家背包
/// </summary>
public interface IPlayerInventory
{
/// <summary>
/// 背包
/// </summary>
public IRuntimeItemContainer Container { get; }
/// <summary>
/// 拾取物品的工厂方法
/// </summary>
event Action<IRuntimeItem> OnPickupItemFactory;
/// <summary>
/// 使用物品的工厂方法,如果返回true则代表物品已被其他逻辑处理
/// </summary>
event Action<IRuntimeItem> UseFactory;
/// <summary>
/// 使用物品的事件,如果返回true则代表物品已被其他逻辑处理
/// </summary>
event Action<IRuntimeItem> OnUsedItem;
void UseItem(int id);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7d743b00f286c04985e59bc3d610882
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,81 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BITKit;
using BITKit.StateMachine;
namespace Net.Project.B.Inventory
{
/// <summary>
/// 玩家武器槽
/// </summary>
public enum PlayerWeaponSlot
{
/// <summary>
/// 主武器
/// </summary>
Primary,
/// <summary>
/// 主武器2
/// </summary>
Secondary,
/// <summary>
/// 副武器,例如手枪,近战武器等
/// </summary>
Sidearm,
/// <summary>
/// 消耗品,通常是护甲,医疗包等
/// </summary>
Supplies,
/// <summary>
/// 战术道具
/// </summary>
Tactics,
/// <summary>
/// 致命道具
/// </summary>
Lethal,
/// <summary>
/// 连杀奖励,特别的武器
/// </summary>
KillStreak
}
/// <summary>
/// 玩家武器控制器
/// </summary>
public interface IPlayerWeaponController:IStateAsync{}
/// <summary>
/// 玩家枪支控制器
/// </summary>
public interface IPlayerGunController:IPlayerWeaponController{}
/// <summary>
/// 玩家近战武器控制器
/// </summary>
public interface IPlayerMeleeController:IPlayerWeaponController{}
/// <summary>
/// 玩家武器库存,与背包不是一个东西
/// </summary>
public interface IPlayerWeaponInventory
{
/// <summary>
/// 武器槽
/// </summary>
public IReadOnlyDictionary<PlayerWeaponSlot,int> WeaponSlots { get; }
/// <summary>
/// 武器控制器状态机
/// </summary>
public IStateMachine<IPlayerWeaponController> StateMachine { get; }
/// <summary>
/// 武器槽更新回调,参数为:slot,ItemId,IsAdd
/// </summary>
public event Action<PlayerWeaponSlot, int, bool> OnWeaponSlotChanged;
/// <summary>
/// 丢下武器
/// </summary>
/// <param name="slot"></param>
void Drop(PlayerWeaponSlot slot);
void Use(PlayerWeaponSlot slot);
void Use(int id);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d7346ddba01563842a9e9c4b3438609b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Src/Item.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2d0475018ba6c5c43b43ff42a24e7bd3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,22 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using BITKit;
using Cysharp.Threading.Tasks;
using Unity.Mathematics;
namespace Net.Project.B.Item
{
public interface IManagedItemService
{
public IReadOnlyDictionary<int,IRuntimeItem> Items { get; }
public void AddOrUpdateItem(IRuntimeItem item);
public void InstanceItem(float3 position, quaternion rotation, IRuntimeItem item);
public void DisposeItem(IRuntimeItem item);
public void DisposeWorldObject(IRuntimeItem item);
public UniTask ReloadAsync();
public event Action<IRuntimeItem> OnItemAddedOrUpdated;
public event Action<IRuntimeItem> OnItemDisposed;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f492654306a018c429fdc97ef6abef58
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
{
"name": "Net.Project.B.Item",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:677cd05ca06c46b4395470200b1acdad",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:d8b63aba1907145bea998dd612889d6b"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f3613c0168f084d4e85ef0501bfa7392
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

3
Src/Lobby.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a4084d10e7034699950a1b849cc65eac
timeCreated: 1724412982

View File

@ -0,0 +1,17 @@
{
"name": "Com.Project.B.Lobby",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9bf0c8dbe7a241c4e8aaeb76035bfdaf
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

87
Src/Lobby/ILobbyData.cs Normal file
View File

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Com.Project.B.Lobby
{
/// <summary>
/// 大厅授权
/// </summary>
public enum LobbyAccessMode
{
/// <summary>
/// 私密大厅
/// </summary>
Private,
/// <summary>
/// 公开,可被搜索到
/// </summary>
Public,
/// <summary>
/// 仅好友可见
/// </summary>
FriendsOnly,
/// <summary>
/// 仅邀请可见
/// </summary>
InviteOnly,
/// <summary>
/// 好友和邀请
/// </summary>
FriendAndInvite,
}
/// <summary>
/// 大厅数据
/// </summary>
public interface ILobbyData
{
/// <summary>
/// 大厅ID,通常是玩家ID
/// </summary>
public Guid Id { get; }
/// <summary>
/// 开放模式
/// </summary>
LobbyAccessMode LobbyAccess { get; }
/// <summary>
/// 选择的场景
/// </summary>
public string Map { get; }
/// <summary>
/// 大厅名称
/// </summary>
public string Name { get; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; }
/// <summary>
/// 主机ID,通常是玩家ID
/// </summary>
public Guid HostId { get; }
/// <summary>
/// 玩家ID
/// </summary>
public Guid[] PlayerIds { get; }
public bool Contain(Guid player);
}
public sealed class LobbyData:ILobbyData
{
public Guid Id { get; set; }
public LobbyAccessMode LobbyAccess { get; set; } = LobbyAccessMode.Public;
public string Map { get; set; }
public string Name { get; set; } = "Project B Lobby";
public string Description { get; set; }="Welcome";
public Guid HostId { get; set; }
[JsonIgnore]
Guid[] ILobbyData.PlayerIds=>Players.ToArray();
public bool Contain(Guid player)
{
return Players.Contains(player) || HostId == player;
}
public List<Guid> Players = new();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 32934edab554437a8cfe71b1e7691b4f
timeCreated: 1724413203

View File

@ -0,0 +1,99 @@
using System;
using BITKit;
using Cysharp.Threading.Tasks;
namespace Com.Project.B.Lobby
{
/// <summary>
/// 大厅服务
/// </summary>
public interface ILobbyServices
{
/// <summary>
/// 获取玩家所在的大厅
/// </summary>
/// <param name="playerId"></param>
/// <returns></returns>
UniTask<ContextModel> GetPlayerLobbyAsync(Guid playerId);
/// <summary>
/// 获取所有大厅
/// </summary>
/// <returns></returns>
UniTask<ILobbyData[]> GetAllLobbyDataAsync();
/// <summary>
/// 创建大厅
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
UniTask<ILobbyData> CreateLobbyAsync(ILobbyData data);
/// <summary>
/// 加入大厅
/// </summary>
/// <param name="playerId"></param>
/// <param name="lobbyId"></param>
/// <returns></returns>
UniTask<ILobbyData> JoinLobbyAsync(Guid playerId,Guid lobbyId);
/// <summary>
/// 离开大厅
/// </summary>
/// <param name="playerId"></param>
/// <param name="lobbyId"></param>
/// <returns></returns>
UniTask<ILobbyData> LeaveLobbyAsync(Guid playerId,Guid lobbyId);
/// <summary>
/// 更新大厅信息
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
UniTask<ILobbyData> UpdateLobbyAsync(ILobbyData data);
/// <summary>
/// 正式释放大厅,通常是游戏开始后
/// </summary>
/// <param name="lobbyId"></param>
/// <returns></returns>
UniTask<ILobbyData> ReleaseLobbyAsync(Guid lobbyId);
/// <summary>
/// 释放大厅,通常是主机离线或加入其他人的大厅
/// </summary>
/// <param name="lobbyId"></param>
/// <returns></returns>
UniTask<ILobbyData> DisposeLobbyAsync(Guid lobbyId);
/// <summary>
/// 邀请玩家加入大厅
/// </summary>
/// <returns></returns>
UniTask InviteToLobbyAsync(Guid inviterId,Guid inviteeId,Guid lobbyId);
/// <summary>
/// 是否接受邀请
/// </summary>
/// <param name="playerId"></param>
/// <param name="lobbyId"></param>
/// <param name="accept"></param>
/// <returns></returns>
UniTask AccessLobbyInviteAsync(Guid playerId,Guid lobbyId,bool accept);
/// <summary>
/// 当大厅创建时
/// </summary>
event Action<ILobbyData> OnLobbyCreated;
/// <summary>
/// 当大厅更新时
/// </summary>
event Action<ILobbyData> OnLobbyUpdated;
/// <summary>
/// 当大厅正式释放时
/// </summary>
event Action<ILobbyData> OnLobbyReleased;
/// <summary>
/// 当大厅释放时
/// </summary>
event Action<ILobbyData> OnLobbyDisposed;
/// <summary>
/// 当邀请加入大厅时
/// </summary>
event Action<Guid,ILobbyData> OnInviteToLobby;
/// <summary>
/// 当拒绝或接受邀请时
/// </summary>
event Action<Guid,ILobbyData> OnAccessLobbyInvite;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2ca5119e773d49159573f88c6d35f987
timeCreated: 1724413181

8
Src/Net.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 781f78b6186d76441831eb8d0f3c6854
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,16 @@
{
"name": "Com.Project.B.Net",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a4033552c5c40fa408838a1ce2b1b215
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BITKit;
using BITKit.StateMachine;
namespace Project.B.Net
{
public interface IGameNetState:IState{}
public interface IGameNetOffline:IGameNetState{}
public interface IGameNetAsHost : IGameNetState
{
}
public interface IGameNetAsClient : IGameNetState
{
}
public interface IGameNetService:IStateMachine<IGameNetState>,IDisposable
{
public INetServer Server { get; }
public INetClient Client { get; }
public INetClient LobbyClient { get; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b586b11f2d79b8b4fbe7c50bb4ae851f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Src/Player.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 166a2e39de2fd344cb5419c5e4fe22ea
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
{
"name": "Com.Project.B.Player",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2d0943973658ff5419a52132fdc2812c
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

45
Src/Player/IPlayerData.cs Normal file
View File

@ -0,0 +1,45 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MemoryPack;
namespace Project.B.Player
{
public interface IPlayerData
{
/// <summary>
/// 用户ID
/// </summary>
Guid PlayerId { get; }
/// <summary>
/// 是否是机器人
/// </summary>
bool IsBot { get; }
/// <summary>
/// Steam64位ID
/// </summary>
long Steam64Id { get; }
/// <summary>
/// https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/xx/xx.jpg
/// </summary>
string AvatarUrl { get; }
/// <summary>
/// 用户名
/// </summary>
string NickName { get; }
/// <summary>
/// 许可证状态
/// </summary>
int LicenseLevel { get; }
}
[MemoryPackable]
public partial struct PlayerData:IPlayerData
{
public Guid PlayerId { get; set; }
public bool IsBot { get; set; }
public long Steam64Id { get; set; }
public string AvatarUrl { get; set; }
public string NickName { get; set; }
public int LicenseLevel { get; set; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5643896287a5a394799a8172a15485d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace Project.B.Player
{
public interface IPlayerService
{
/// <summary>
/// 获取玩家信息
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
UniTask<IPlayerData> GetPlayerDataAsync(Guid id);
/// <summary>
/// 获取玩家信息
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
UniTask<IReadOnlyCollection<IPlayerData>> GetPlayersDataAsync(IReadOnlyCollection<Guid> ids);
/// <summary>
/// 创建或更新玩家信息
/// </summary>
/// <param name="playerData"></param>
/// <returns></returns>
UniTask<IPlayerData> CreateOrUpdatePlayerAsync(IPlayerData playerData);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8de5d3a0ae5b33947ae38fe3e415dae3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Src/PlayerSettings.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2229713342b60434b949bf1a30a64614
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More