Entity system
This commit is contained in:
parent
13cfd2468f
commit
7392b2d20a
26 changed files with 595 additions and 216 deletions
|
@ -1,4 +1,4 @@
|
|||
using GameServer.Controllers.Event;
|
||||
using GameServer.Systems.Event;
|
||||
|
||||
namespace GameServer.Controllers.Attributes;
|
||||
|
||||
|
|
147
GameServer/Controllers/CreatureController.cs
Normal file
147
GameServer/Controllers/CreatureController.cs
Normal file
|
@ -0,0 +1,147 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Models;
|
||||
using GameServer.Network;
|
||||
using GameServer.Network.Messages;
|
||||
using GameServer.Systems.Entity;
|
||||
using GameServer.Systems.Entity.Component;
|
||||
using GameServer.Systems.Event;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Controllers;
|
||||
internal class CreatureController : Controller
|
||||
{
|
||||
private readonly EntitySystem _entitySystem;
|
||||
private readonly EntityFactory _entityFactory;
|
||||
private readonly ModelManager _modelManager;
|
||||
|
||||
public CreatureController(PlayerSession session, EntitySystem entitySystem, EntityFactory entityFactory, ModelManager modelManager) : base(session)
|
||||
{
|
||||
_entitySystem = entitySystem;
|
||||
_entityFactory = entityFactory;
|
||||
_modelManager = modelManager;
|
||||
}
|
||||
|
||||
public async Task JoinScene(int instanceId)
|
||||
{
|
||||
_modelManager.Creature.SetSceneLoadingData(instanceId);
|
||||
CreateInitialPlayer();
|
||||
|
||||
await Session.Push(MessageId.JoinSceneNotify, new JoinSceneNotify
|
||||
{
|
||||
MaxEntityId = 10000,
|
||||
TransitionOption = new TransitionOptionPb
|
||||
{
|
||||
TransitionType = (int)TransitionType.Empty
|
||||
},
|
||||
SceneInfo = CreateSceneInfo()
|
||||
});
|
||||
}
|
||||
|
||||
[NetEvent(MessageId.EntityActiveRequest)]
|
||||
public async Task<ResponseMessage> OnEntityActiveRequest(EntityActiveRequest request)
|
||||
{
|
||||
EntityActiveResponse response;
|
||||
|
||||
EntityBase? entity = _entitySystem.Get<EntityBase>(request.EntityId);
|
||||
if (entity != null)
|
||||
{
|
||||
_entitySystem.Activate(entity);
|
||||
response = new EntityActiveResponse
|
||||
{
|
||||
ErrorCode = (int)ErrorCode.Success
|
||||
};
|
||||
|
||||
response.ComponentPbs.AddRange(entity.ComponentSystem.Pb);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = new EntityActiveResponse { ErrorCode = (int)ErrorCode.ErrActionEntityNoExist };
|
||||
}
|
||||
|
||||
await OnVisionSkillChanged();
|
||||
return Response(MessageId.EntityActiveResponse, response);
|
||||
}
|
||||
|
||||
[NetEvent(MessageId.SceneLoadingFinishRequest)]
|
||||
public ResponseMessage OnSceneLoadingFinishRequest()
|
||||
{
|
||||
_modelManager.Creature.OnWorldDone();
|
||||
|
||||
return Response(MessageId.SceneLoadingFinishResponse, new SceneLoadingFinishResponse());
|
||||
}
|
||||
|
||||
[GameEvent(GameEventType.VisionSkillChanged)]
|
||||
public async Task OnVisionSkillChanged()
|
||||
{
|
||||
PlayerEntity? playerEntity = GetPlayerEntity(_modelManager.Player.Id);
|
||||
if (playerEntity == null) return;
|
||||
|
||||
EntityVisionSkillComponent visionSkillComponent = playerEntity.ComponentSystem.Get<EntityVisionSkillComponent>();
|
||||
|
||||
VisionSkillChangeNotify skillChangeNotify = new() { EntityId = playerEntity.Id };
|
||||
skillChangeNotify.VisionSkillInfos.AddRange(visionSkillComponent.Skills);
|
||||
|
||||
await Session.Push(MessageId.VisionSkillChangeNotify, skillChangeNotify);
|
||||
}
|
||||
|
||||
public PlayerEntity? GetPlayerEntity(int playerId)
|
||||
{
|
||||
return _entitySystem.EnumerateEntities().FirstOrDefault(entity => entity is PlayerEntity p && p.PlayerId == playerId) as PlayerEntity;
|
||||
}
|
||||
|
||||
private SceneInformation CreateSceneInfo()
|
||||
{
|
||||
SceneInformation scene = new()
|
||||
{
|
||||
InstanceId = _modelManager.Creature.InstanceId,
|
||||
OwnerId = _modelManager.Creature.OwnerId,
|
||||
CurContextId = _modelManager.Player.Id,
|
||||
TimeInfo = new(),
|
||||
AoiData = new(),
|
||||
PlayerInfos =
|
||||
{
|
||||
new ScenePlayerInformation
|
||||
{
|
||||
PlayerId = _modelManager.Player.Id,
|
||||
Level = 1,
|
||||
IsOffline = false,
|
||||
Location = new()
|
||||
{
|
||||
X = 4000,
|
||||
Y = -2000,
|
||||
Z = 260
|
||||
},
|
||||
FightRoleInfos =
|
||||
{
|
||||
new FightRoleInformation
|
||||
{
|
||||
EntityId = 1,
|
||||
CurHp = 1000,
|
||||
MaxHp = 1000,
|
||||
IsControl = true,
|
||||
RoleId = _modelManager.Player.CharacterId,
|
||||
RoleLevel = 1,
|
||||
}
|
||||
},
|
||||
PlayerName = _modelManager.Player.Name
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scene.AoiData.Entities.AddRange(_entitySystem.Pb);
|
||||
return scene;
|
||||
}
|
||||
|
||||
private void CreateInitialPlayer()
|
||||
{
|
||||
PlayerEntity entity = _entityFactory.CreatePlayer(1601, _modelManager.Player.Id);
|
||||
entity.Pos = new()
|
||||
{
|
||||
X = 4000,
|
||||
Y = -2000,
|
||||
Z = 260
|
||||
};
|
||||
|
||||
_entitySystem.Create(entity);
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
namespace GameServer.Controllers.Event;
|
||||
internal enum GameEventType
|
||||
{
|
||||
Login = 1,
|
||||
EnterGame
|
||||
}
|
|
@ -2,8 +2,8 @@
|
|||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Network.Messages;
|
||||
using GameServer.Systems.Event;
|
||||
using Google.Protobuf;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Network;
|
||||
using GameServer.Systems.Event;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Controllers;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Network;
|
||||
using GameServer.Network.Messages;
|
||||
using GameServer.Systems.Event;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Protocol;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using GameServer.Controllers.Event;
|
||||
using GameServer.Controllers.Factory;
|
||||
using GameServer.Network;
|
||||
using GameServer.Controllers.Factory;
|
||||
using GameServer.Systems.Event;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace GameServer.Controllers.Manager;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Models;
|
||||
using GameServer.Network;
|
||||
using GameServer.Systems.Event;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Controllers;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Models;
|
||||
using GameServer.Network;
|
||||
using GameServer.Network.Messages;
|
||||
using GameServer.Systems.Event;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Controllers;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Models;
|
||||
using GameServer.Network;
|
||||
using GameServer.Network.Messages;
|
||||
using GameServer.Systems.Entity;
|
||||
using GameServer.Systems.Entity.Component;
|
||||
using GameServer.Systems.Event;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Controllers;
|
||||
|
@ -38,19 +41,15 @@ internal class RouletteController : Controller
|
|||
}
|
||||
|
||||
[NetEvent(MessageId.VisionExploreSkillSetRequest)]
|
||||
public async Task<ResponseMessage> OnVisionExploreSkillSetRequest(VisionExploreSkillSetRequest request)
|
||||
public async Task<ResponseMessage> OnVisionExploreSkillSetRequest(VisionExploreSkillSetRequest request, CreatureController creatureController, ModelManager modelManager, EventSystem eventSystem)
|
||||
{
|
||||
await Session.Push(MessageId.VisionSkillChangeNotify, new VisionSkillChangeNotify
|
||||
{
|
||||
EntityId = 1,
|
||||
VisionSkillInfos =
|
||||
{
|
||||
new VisionSkillInformation
|
||||
{
|
||||
SkillId = request.SkillId
|
||||
}
|
||||
}
|
||||
});
|
||||
PlayerEntity? playerEntity = creatureController.GetPlayerEntity(modelManager.Player.Id);
|
||||
if (playerEntity == null) return Response(MessageId.VisionExploreSkillSetResponse, new VisionExploreSkillSetResponse { ErrCode = (int)ErrorCode.PlayerNotInAnyScene });
|
||||
|
||||
EntityVisionSkillComponent visionSkillComponent = playerEntity.ComponentSystem.Get<EntityVisionSkillComponent>();
|
||||
visionSkillComponent.SetExploreTool(request.SkillId);
|
||||
|
||||
await eventSystem.Emit(GameEventType.VisionSkillChanged);
|
||||
|
||||
return Response(MessageId.VisionExploreSkillSetResponse, new VisionExploreSkillSetResponse
|
||||
{
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Models;
|
||||
using GameServer.Network;
|
||||
using GameServer.Network.Messages;
|
||||
using GameServer.Systems.Event;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Controllers;
|
||||
|
@ -14,187 +13,11 @@ internal class WorldController : Controller
|
|||
}
|
||||
|
||||
[GameEvent(GameEventType.EnterGame)]
|
||||
public async Task OnEnterGame(ModelManager modelManager)
|
||||
public async Task OnEnterGame(CreatureController creatureController)
|
||||
{
|
||||
PlayerModel player = modelManager.Player;
|
||||
|
||||
await Session.Push(MessageId.JoinSceneNotify, new JoinSceneNotify
|
||||
{
|
||||
MaxEntityId = 2,
|
||||
TransitionOption = new TransitionOptionPb
|
||||
{
|
||||
TransitionType = (int)TransitionType.Empty
|
||||
},
|
||||
SceneInfo = new SceneInformation
|
||||
{
|
||||
OwnerId = player.Id,
|
||||
Mode = (int)SceneMode.Single,
|
||||
InstanceId = 8,
|
||||
AoiData = new PlayerSceneAoiData
|
||||
{
|
||||
GenIds = { 1 },
|
||||
Entities =
|
||||
{
|
||||
new EntityPb
|
||||
{
|
||||
EntityState = (int)EntityState.Born,
|
||||
EntityType = (int)EEntityType.Player,
|
||||
PlayerId = player.Id,
|
||||
LivingStatus = (int)LivingStatus.Alive,
|
||||
ConfigId = player.CharacterId,
|
||||
ConfigType = (int)EntityConfigType.Character,
|
||||
Id = 1,
|
||||
IsVisible = true,
|
||||
Pos = new Vector
|
||||
{
|
||||
X = 4000,
|
||||
Y = -2000,
|
||||
Z = 260
|
||||
},
|
||||
Rot = new(),
|
||||
InitLinearVelocity = new(),
|
||||
PrefabIncId = 0,
|
||||
InitPos = new Vector
|
||||
{
|
||||
X = 4000,
|
||||
Y = -2000,
|
||||
Z = 260
|
||||
},
|
||||
ComponentPbs =
|
||||
{
|
||||
new EntityComponentPb
|
||||
{
|
||||
VisionSkillComponent = new VisionSkillComponentPb
|
||||
{
|
||||
VisionSkillInfos =
|
||||
{
|
||||
new VisionSkillInformation
|
||||
{
|
||||
SkillId = 1001
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new EntityComponentPb
|
||||
{
|
||||
AttributeComponent = new AttributeComponentPb
|
||||
{
|
||||
GameAttributes =
|
||||
{
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.Life,
|
||||
BaseValue = 1000,
|
||||
CurrentValue = 1000
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.LifeMax,
|
||||
BaseValue = 1000,
|
||||
CurrentValue = 1000
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.EnergyMax,
|
||||
BaseValue = 10,
|
||||
CurrentValue = 10
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.Energy,
|
||||
BaseValue = 10,
|
||||
CurrentValue = 10
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.SpecialEnergy3,
|
||||
BaseValue = 10,
|
||||
CurrentValue = 10
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.SpecialEnergy3Max,
|
||||
BaseValue = 10,
|
||||
CurrentValue = 10
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.AutoAttackSpeed,
|
||||
BaseValue = 10000,
|
||||
CurrentValue = 10000
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.CastAttackSpeed,
|
||||
BaseValue = 10000,
|
||||
CurrentValue = 10000
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.Atk,
|
||||
BaseValue = 1,
|
||||
CurrentValue = 1
|
||||
},
|
||||
new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)EAttributeType.Lv,
|
||||
BaseValue = 1,
|
||||
CurrentValue = 1
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
new EntityComponentPb
|
||||
{
|
||||
ConcomitantsComponentPb = new ConcomitantsComponentPb
|
||||
{
|
||||
CustomEntityIds = {1},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
TimeInfo = new SceneTimeInfo
|
||||
{
|
||||
Hour = 23
|
||||
},
|
||||
PlayerInfos =
|
||||
{
|
||||
new ScenePlayerInformation
|
||||
{
|
||||
PlayerId = player.Id,
|
||||
Level = 1,
|
||||
IsOffline = false,
|
||||
Location = new()
|
||||
{
|
||||
X = 4000,
|
||||
Y = -2000,
|
||||
Z = 260
|
||||
},
|
||||
FightRoleInfos =
|
||||
{
|
||||
new FightRoleInformation
|
||||
{
|
||||
EntityId = 1,
|
||||
CurHp = 1000,
|
||||
MaxHp = 1000,
|
||||
IsControl = true,
|
||||
RoleId = player.CharacterId,
|
||||
RoleLevel = 1,
|
||||
}
|
||||
},
|
||||
PlayerName = player.Name
|
||||
}
|
||||
},
|
||||
CurContextId = player.Id
|
||||
}
|
||||
});
|
||||
await creatureController.JoinScene(8);
|
||||
}
|
||||
|
||||
[NetEvent(MessageId.EntityActiveRequest)]
|
||||
public ResponseMessage OnEntityActiveRequest() => Response(MessageId.EntityActiveResponse, new EntityActiveResponse());
|
||||
|
||||
[NetEvent(MessageId.EntityOnLandedRequest)]
|
||||
public ResponseMessage OnEntityOnLandedRequest() => Response(MessageId.EntityOnLandedResponse, new EntityOnLandedResponse());
|
||||
|
||||
|
@ -204,9 +27,6 @@ internal class WorldController : Controller
|
|||
[NetEvent(MessageId.EntityLoadCompleteRequest)]
|
||||
public ResponseMessage OnEntityLoadCompleteRequest() => Response(MessageId.EntityLoadCompleteResponse, new EntityLoadCompleteResponse());
|
||||
|
||||
[NetEvent(MessageId.SceneLoadingFinishRequest)]
|
||||
public ResponseMessage OnSceneLoadingFinishRequest() => Response(MessageId.SceneLoadingFinishResponse, new SceneLoadingFinishResponse());
|
||||
|
||||
[NetEvent(MessageId.UpdateSceneDateRequest)]
|
||||
public ResponseMessage OnUpdateSceneDateRequest() => Response(MessageId.UpdateSceneDateResponse, new UpdateSceneDateResponse());
|
||||
}
|
||||
|
|
26
GameServer/Models/CreatureModel.cs
Normal file
26
GameServer/Models/CreatureModel.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
namespace GameServer.Models;
|
||||
internal class CreatureModel
|
||||
{
|
||||
public int OwnerId { get; }
|
||||
|
||||
public int InstanceId { get; private set; }
|
||||
public bool LoadingWorld { get; private set; }
|
||||
|
||||
public long PlayerEntityId { get; set; }
|
||||
|
||||
public CreatureModel(int ownerId)
|
||||
{
|
||||
OwnerId = ownerId;
|
||||
}
|
||||
|
||||
public void SetSceneLoadingData(int instanceId)
|
||||
{
|
||||
InstanceId = instanceId;
|
||||
LoadingWorld = true;
|
||||
}
|
||||
|
||||
public void OnWorldDone()
|
||||
{
|
||||
LoadingWorld = false;
|
||||
}
|
||||
}
|
|
@ -1,16 +1,20 @@
|
|||
using GameServer.Controllers.Attributes;
|
||||
using GameServer.Controllers.Event;
|
||||
using GameServer.Systems.Event;
|
||||
|
||||
namespace GameServer.Models;
|
||||
internal class ModelManager
|
||||
{
|
||||
private PlayerModel? _playerModel;
|
||||
private CreatureModel? _creatureModel;
|
||||
|
||||
[GameEvent(GameEventType.Login)]
|
||||
public void OnLogin()
|
||||
{
|
||||
_playerModel = PlayerModel.CreateDefaultPlayer();
|
||||
_creatureModel = new CreatureModel(_playerModel.Id);
|
||||
}
|
||||
|
||||
public PlayerModel Player => _playerModel ?? throw new InvalidOperationException($"Trying to access {nameof(PlayerModel)} instance before initialization!");
|
||||
|
||||
public CreatureModel Creature => _creatureModel ?? throw new InvalidOperationException($"Trying to access {nameof(CreatureModel)} instance before initialization!");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using GameServer.Controllers.Event;
|
||||
using GameServer.Controllers.Factory;
|
||||
using GameServer.Controllers.Factory;
|
||||
using GameServer.Controllers.Manager;
|
||||
using GameServer.Extensions;
|
||||
using GameServer.Models;
|
||||
|
@ -7,6 +6,8 @@ using GameServer.Network;
|
|||
using GameServer.Network.Kcp;
|
||||
using GameServer.Network.Messages;
|
||||
using GameServer.Network.Rpc;
|
||||
using GameServer.Systems.Entity;
|
||||
using GameServer.Systems.Event;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -25,7 +26,8 @@ internal static class Program
|
|||
.AddScoped<MessageManager>().AddSingleton<EventHandlerFactory>()
|
||||
.AddScoped<RpcManager>().AddScoped<IRpcEndPoint, RpcSessionEndPoint>()
|
||||
.AddSingleton<SessionManager>()
|
||||
.AddScoped<EventSystem>().AddScoped<ModelManager>().AddScoped<ControllerManager>()
|
||||
.AddScoped<EventSystem>().AddScoped<EntitySystem>().AddScoped<EntityFactory>()
|
||||
.AddScoped<ModelManager>().AddScoped<ControllerManager>()
|
||||
.AddHostedService<WWGameServer>();
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity.Component;
|
||||
internal class EntityAttributeComponent : EntityComponentBase
|
||||
{
|
||||
public override EntityComponentType Type => EntityComponentType.Attribute;
|
||||
|
||||
private readonly Dictionary<EAttributeType, GameplayAttributeData> _gameplayAttributes;
|
||||
|
||||
public EntityAttributeComponent()
|
||||
{
|
||||
_gameplayAttributes = [];
|
||||
}
|
||||
|
||||
public void SetAttribute(EAttributeType type, int currentValue, int baseValue)
|
||||
{
|
||||
if (!_gameplayAttributes.TryGetValue(type, out GameplayAttributeData? attribute))
|
||||
{
|
||||
attribute = new GameplayAttributeData
|
||||
{
|
||||
AttributeType = (int)type
|
||||
};
|
||||
|
||||
_gameplayAttributes.Add(type, attribute);
|
||||
}
|
||||
|
||||
attribute.CurrentValue = currentValue;
|
||||
attribute.BaseValue = baseValue;
|
||||
}
|
||||
|
||||
public void SetAttribute(EAttributeType type, int currentValue)
|
||||
{
|
||||
if (!_gameplayAttributes.TryGetValue(type, out GameplayAttributeData? attribute))
|
||||
{
|
||||
SetAttribute(type, currentValue, currentValue);
|
||||
return;
|
||||
}
|
||||
|
||||
attribute.CurrentValue = currentValue;
|
||||
}
|
||||
|
||||
public int GetAttribute(EAttributeType type)
|
||||
{
|
||||
if (_gameplayAttributes.TryGetValue(type, out GameplayAttributeData? attribute))
|
||||
return attribute.CurrentValue;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetAttributeBase(EAttributeType type)
|
||||
{
|
||||
if (_gameplayAttributes.TryGetValue(type, out GameplayAttributeData? attribute))
|
||||
return attribute.BaseValue;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override EntityComponentPb Pb
|
||||
{
|
||||
get
|
||||
{
|
||||
EntityComponentPb pb = new()
|
||||
{
|
||||
AttributeComponent = new()
|
||||
};
|
||||
|
||||
pb.AttributeComponent.GameAttributes.AddRange(_gameplayAttributes.Values);
|
||||
|
||||
return pb;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity.Component;
|
||||
internal abstract class EntityComponentBase
|
||||
{
|
||||
public abstract EntityComponentType Type { get; }
|
||||
public abstract EntityComponentPb Pb { get; }
|
||||
}
|
34
GameServer/Systems/Entity/Component/EntityComponentSystem.cs
Normal file
34
GameServer/Systems/Entity/Component/EntityComponentSystem.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity.Component;
|
||||
internal class EntityComponentSystem
|
||||
{
|
||||
private readonly List<EntityComponentBase> _components;
|
||||
|
||||
public EntityComponentSystem()
|
||||
{
|
||||
_components = [];
|
||||
}
|
||||
|
||||
public TEntityComponent Create<TEntityComponent>() where TEntityComponent : EntityComponentBase, new()
|
||||
{
|
||||
if (_components.Any(component => component is TEntityComponent)) throw new InvalidOperationException($"Component of type {nameof(TEntityComponent)} already exists");
|
||||
|
||||
TEntityComponent component = new();
|
||||
_components.Add(component);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
public TEntityComponent Get<TEntityComponent>() where TEntityComponent : EntityComponentBase
|
||||
{
|
||||
return (_components.Single(component => component is TEntityComponent) as TEntityComponent)!;
|
||||
}
|
||||
|
||||
public bool TryGet<TEntityComponent>(out TEntityComponent? component) where TEntityComponent : EntityComponentBase
|
||||
{
|
||||
return (component = _components.SingleOrDefault(component => component is TEntityComponent) as TEntityComponent) != null;
|
||||
}
|
||||
|
||||
public IEnumerable<EntityComponentPb> Pb => _components.Select(component => component.Pb);
|
||||
}
|
37
GameServer/Systems/Entity/Component/EntityComponentType.cs
Normal file
37
GameServer/Systems/Entity/Component/EntityComponentType.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
namespace GameServer.Systems.Entity.Component;
|
||||
internal enum EntityComponentType
|
||||
{
|
||||
Attribute,
|
||||
Tag,
|
||||
Trigger,
|
||||
Summoner,
|
||||
Part,
|
||||
VisionSkill,
|
||||
AnimationState,
|
||||
BlackboardParam,
|
||||
SysBuff,
|
||||
ClientData,
|
||||
MonsterWeapon,
|
||||
MonsterAi,
|
||||
FightBuff,
|
||||
NearbyTracking,
|
||||
Drop,
|
||||
MonsterCapture,
|
||||
LogicState,
|
||||
Advice,
|
||||
Lift,
|
||||
Interact,
|
||||
Equip,
|
||||
BeControlled,
|
||||
Concomitants,
|
||||
TimelineTrack,
|
||||
Summons,
|
||||
EntityFsm,
|
||||
Board,
|
||||
PlacementItem,
|
||||
StateTag,
|
||||
MonsterGachaData,
|
||||
Fan,
|
||||
Npc,
|
||||
Bubble
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity.Component;
|
||||
internal class EntityConcomitantsComponent : EntityComponentBase
|
||||
{
|
||||
public List<long> CustomEntityIds { get; }
|
||||
|
||||
public EntityConcomitantsComponent()
|
||||
{
|
||||
CustomEntityIds = [];
|
||||
}
|
||||
|
||||
public override EntityComponentType Type => EntityComponentType.Concomitants;
|
||||
|
||||
public override EntityComponentPb Pb
|
||||
{
|
||||
get
|
||||
{
|
||||
EntityComponentPb pb = new()
|
||||
{
|
||||
ConcomitantsComponentPb = new()
|
||||
};
|
||||
|
||||
pb.ConcomitantsComponentPb.CustomEntityIds.AddRange(CustomEntityIds);
|
||||
return pb;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity.Component;
|
||||
internal class EntityVisionSkillComponent : EntityComponentBase
|
||||
{
|
||||
public List<VisionSkillInformation> Skills { get; }
|
||||
|
||||
public EntityVisionSkillComponent()
|
||||
{
|
||||
Skills = [];
|
||||
}
|
||||
|
||||
public void SetExploreTool(int toolId)
|
||||
{
|
||||
Skills.Clear();
|
||||
Skills.Add(new VisionSkillInformation
|
||||
{
|
||||
SkillId = toolId
|
||||
});
|
||||
}
|
||||
|
||||
public override EntityComponentType Type => EntityComponentType.VisionSkill;
|
||||
|
||||
public override EntityComponentPb Pb
|
||||
{
|
||||
get
|
||||
{
|
||||
EntityComponentPb pb = new()
|
||||
{
|
||||
VisionSkillComponent = new VisionSkillComponentPb()
|
||||
};
|
||||
|
||||
pb.VisionSkillComponent.VisionSkillInfos.AddRange(Skills);
|
||||
return pb;
|
||||
}
|
||||
}
|
||||
}
|
49
GameServer/Systems/Entity/EntityBase.cs
Normal file
49
GameServer/Systems/Entity/EntityBase.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using GameServer.Systems.Entity.Component;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity;
|
||||
internal abstract class EntityBase
|
||||
{
|
||||
public long Id { get; }
|
||||
public EntityComponentSystem ComponentSystem { get; }
|
||||
|
||||
public Vector Pos { get; set; }
|
||||
public Rotator Rot { get; set; }
|
||||
|
||||
public bool Active { get; set; }
|
||||
|
||||
public EntityState State { get; protected set; }
|
||||
|
||||
public EntityBase(long id)
|
||||
{
|
||||
Id = id;
|
||||
|
||||
Pos = new Vector();
|
||||
Rot = new Rotator();
|
||||
|
||||
ComponentSystem = new EntityComponentSystem();
|
||||
}
|
||||
|
||||
public virtual void OnCreate()
|
||||
{
|
||||
State = EntityState.Born;
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
AddComponents();
|
||||
}
|
||||
|
||||
public virtual void AddComponents()
|
||||
{
|
||||
// AddComponents.
|
||||
}
|
||||
|
||||
public virtual LivingStatus LivingStatus => LivingStatus.Alive;
|
||||
public virtual bool IsVisible => true;
|
||||
|
||||
public abstract EEntityType Type { get; }
|
||||
public abstract EntityConfigType ConfigType { get; }
|
||||
|
||||
public abstract EntityPb Pb { get; }
|
||||
}
|
10
GameServer/Systems/Entity/EntityFactory.cs
Normal file
10
GameServer/Systems/Entity/EntityFactory.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace GameServer.Systems.Entity;
|
||||
internal class EntityFactory
|
||||
{
|
||||
private long _entityIdCounter;
|
||||
|
||||
public PlayerEntity CreatePlayer(int characterConfigId, int playerId)
|
||||
=> new(NextId(), characterConfigId, playerId);
|
||||
|
||||
private long NextId() => Interlocked.Increment(ref _entityIdCounter);
|
||||
}
|
38
GameServer/Systems/Entity/EntitySystem.cs
Normal file
38
GameServer/Systems/Entity/EntitySystem.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity;
|
||||
internal class EntitySystem
|
||||
{
|
||||
private readonly List<EntityBase> _entities;
|
||||
|
||||
public EntitySystem()
|
||||
{
|
||||
_entities = [];
|
||||
}
|
||||
|
||||
public IEnumerable<EntityBase> EnumerateEntities()
|
||||
{
|
||||
return _entities;
|
||||
}
|
||||
|
||||
public void Create(EntityBase entity)
|
||||
{
|
||||
if (_entities.Any(e => e.Id == entity.Id))
|
||||
throw new InvalidOperationException($"EntitySystem::Create - entity with id {entity.Id} already exists");
|
||||
|
||||
entity.OnCreate();
|
||||
_entities.Add(entity);
|
||||
}
|
||||
|
||||
public void Activate(EntityBase entity)
|
||||
{
|
||||
entity.Activate();
|
||||
}
|
||||
|
||||
public TEntity? Get<TEntity>(long id) where TEntity : EntityBase
|
||||
{
|
||||
return _entities.SingleOrDefault(e => e.Id == id) as TEntity;
|
||||
}
|
||||
|
||||
public IEnumerable<EntityPb> Pb => _entities.Select(e => e.Pb);
|
||||
}
|
66
GameServer/Systems/Entity/PlayerEntity.cs
Normal file
66
GameServer/Systems/Entity/PlayerEntity.cs
Normal file
|
@ -0,0 +1,66 @@
|
|||
using GameServer.Systems.Entity.Component;
|
||||
using Protocol;
|
||||
|
||||
namespace GameServer.Systems.Entity;
|
||||
internal class PlayerEntity : EntityBase
|
||||
{
|
||||
public PlayerEntity(long id, int configId, int playerId) : base(id)
|
||||
{
|
||||
ConfigId = configId;
|
||||
PlayerId = playerId;
|
||||
}
|
||||
|
||||
public int ConfigId { get; }
|
||||
public int PlayerId { get; }
|
||||
|
||||
public override void AddComponents()
|
||||
{
|
||||
base.AddComponents();
|
||||
|
||||
EntityConcomitantsComponent concomitantsComponent = ComponentSystem.Create<EntityConcomitantsComponent>();
|
||||
concomitantsComponent.CustomEntityIds.Add(Id);
|
||||
|
||||
EntityVisionSkillComponent visionSkillComponent = ComponentSystem.Create<EntityVisionSkillComponent>();
|
||||
visionSkillComponent.SetExploreTool(1001);
|
||||
|
||||
_ = ComponentSystem.Create<EntityAttributeComponent>();
|
||||
InitAttributes();
|
||||
}
|
||||
|
||||
private void InitAttributes()
|
||||
{
|
||||
EntityAttributeComponent attributeComponent = ComponentSystem.Get<EntityAttributeComponent>();
|
||||
attributeComponent.SetAttribute(EAttributeType.Life, 1000);
|
||||
attributeComponent.SetAttribute(EAttributeType.LifeMax, 1000);
|
||||
attributeComponent.SetAttribute(EAttributeType.Lv, 1);
|
||||
}
|
||||
|
||||
public override EEntityType Type => EEntityType.Player;
|
||||
public override EntityConfigType ConfigType => EntityConfigType.Character;
|
||||
|
||||
public override EntityPb Pb
|
||||
{
|
||||
get
|
||||
{
|
||||
EntityPb pb = new()
|
||||
{
|
||||
Id = Id,
|
||||
EntityType = (int)Type,
|
||||
ConfigType = (int)ConfigType,
|
||||
EntityState = (int)State,
|
||||
ConfigId = ConfigId,
|
||||
Pos = Pos,
|
||||
Rot = Rot,
|
||||
PlayerId = PlayerId,
|
||||
LivingStatus = (int)LivingStatus,
|
||||
IsVisible = IsVisible,
|
||||
InitLinearVelocity = new(),
|
||||
InitPos = new()
|
||||
};
|
||||
|
||||
pb.ComponentPbs.AddRange(ComponentSystem.Pb);
|
||||
|
||||
return pb;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ using GameServer.Controllers.Manager;
|
|||
using GameServer.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace GameServer.Controllers.Event;
|
||||
namespace GameServer.Systems.Event;
|
||||
internal class EventSystem
|
||||
{
|
||||
private static readonly ImmutableDictionary<GameEventType, Func<ModelManager, Task>> s_modelManagerEventHandlers = RegisterModelManagerEvents();
|
9
GameServer/Systems/Event/GameEventType.cs
Normal file
9
GameServer/Systems/Event/GameEventType.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace GameServer.Systems.Event;
|
||||
internal enum GameEventType
|
||||
{
|
||||
Login = 1,
|
||||
EnterGame,
|
||||
|
||||
// Actions
|
||||
VisionSkillChanged
|
||||
}
|
Loading…
Reference in a new issue