Add initial resource and presenter classes for game entities and effects
This commit is contained in:
80
Code/Factories/ComponentFactory.cs
Normal file
80
Code/Factories/ComponentFactory.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CryptonymThunder.Code.Resources;
|
||||
using GameCore.Attributes;
|
||||
using GameCore.Combat;
|
||||
using GameCore.ECS.Interfaces;
|
||||
using GameCore.Input;
|
||||
using GameCore.Movement;
|
||||
using GameCore.Physics;
|
||||
using GameCore.Player;
|
||||
using Godot;
|
||||
|
||||
namespace CryptonymThunder.Code.Factories;
|
||||
|
||||
public class ComponentFactory
|
||||
{
|
||||
private readonly Dictionary<Type, Func<Resource, IComponent>> _factories = new();
|
||||
private readonly EffectFactory _effectFactory = new();
|
||||
|
||||
public ComponentFactory()
|
||||
{
|
||||
Register<AttributeComponentResource>(CreateAttributeComponent);
|
||||
Register<WeaponComponentResource>(CreateWeaponComponent);
|
||||
Register<ProjectileComponentResource>(CreateProjectileComponent);
|
||||
Register<PositionComponentResource>(_ => new PositionComponent());
|
||||
Register<VelocityComponentResource>(_ => new VelocityComponent());
|
||||
Register<InputStateComponentResource>(_ => new InputStateComponent());
|
||||
Register<PlayerComponentResource>(_ => new PlayerComponent());
|
||||
Register<RotationComponentResource>(_ => new RotationComponent());
|
||||
Register<CharacterStateComponentResource>(_ => new CharacterStateComponent());
|
||||
}
|
||||
|
||||
public IComponent Create(Resource resource)
|
||||
{
|
||||
return _factories.TryGetValue(resource.GetType(), out var factory)
|
||||
? factory(resource)
|
||||
: null;
|
||||
}
|
||||
|
||||
private void Register<TResource>(Func<TResource, IComponent> factory) where TResource : Resource
|
||||
{
|
||||
_factories[typeof(TResource)] = res => factory((TResource)res);
|
||||
}
|
||||
|
||||
private static AttributeComponent CreateAttributeComponent(AttributeComponentResource resource)
|
||||
{
|
||||
var component = new AttributeComponent();
|
||||
foreach (var (attribute, value) in resource.BaseValues)
|
||||
{
|
||||
component.SetBaseValue(attribute, value);
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
private WeaponComponent CreateWeaponComponent(WeaponComponentResource resource)
|
||||
{
|
||||
if (resource.WeaponData == null) return null;
|
||||
var weaponData = resource.WeaponData;
|
||||
|
||||
var onFireEffects = weaponData.OnFireEffects.Select(_effectFactory.Create).ToList();
|
||||
var onHitEffects = weaponData.OnHitEffects.Select(_effectFactory.Create).ToList();
|
||||
|
||||
return new WeaponComponent
|
||||
{
|
||||
FireRate = resource.WeaponData.FireRate,
|
||||
OnFireEffects = onFireEffects,
|
||||
OnHitEffects = onHitEffects,
|
||||
};
|
||||
}
|
||||
|
||||
private ProjectileComponent CreateProjectileComponent(ProjectileComponentResource resource)
|
||||
{
|
||||
return new ProjectileComponent
|
||||
{
|
||||
Lifetime = resource.Lifetime,
|
||||
};
|
||||
}
|
||||
}
|
||||
1
Code/Factories/ComponentFactory.cs.uid
Normal file
1
Code/Factories/ComponentFactory.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cwf0khkssee8b
|
||||
24
Code/Factories/EffectFactory.cs
Normal file
24
Code/Factories/EffectFactory.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using CryptonymThunder.Code.Resources;
|
||||
using CryptonymThunder.Code.Resources.Effects;
|
||||
using GameCore.Combat.Effects;
|
||||
using GameCore.Combat.Interfaces;
|
||||
|
||||
namespace CryptonymThunder.Code.Factories;
|
||||
|
||||
public class EffectFactory
|
||||
{
|
||||
public IEffect Create(EffectResource resource)
|
||||
{
|
||||
return resource switch
|
||||
{
|
||||
FireProjectileEffectResource fire =>
|
||||
new BulkProjectileEffect(fire.ProjectileArchetypeId, fire.Count, fire.SpreadAngle, fire.ProjectileSpeed),
|
||||
DamageEffectResource damage => new DamageEffect(damage.Amount),
|
||||
HitscanEffectResource hitscan => new HitscanEffect(hitscan.Range),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(resource),
|
||||
$"Effect type {resource.GetType().Name} not recognized")
|
||||
};
|
||||
}
|
||||
}
|
||||
1
Code/Factories/EffectFactory.cs.uid
Normal file
1
Code/Factories/EffectFactory.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://d1n7re7y0g6q4
|
||||
99
Code/Factories/PresenterFactory.cs
Normal file
99
Code/Factories/PresenterFactory.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System.Collections.Generic;
|
||||
using CryptonymThunder.Code.Autoloads;
|
||||
using CryptonymThunder.Code.Resources;
|
||||
using GameCore.ECS;
|
||||
using GameCore.ECS.Interfaces;
|
||||
using GameCore.Movement;
|
||||
using GameCore.Physics;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace CryptonymThunder.Code.Factories;
|
||||
|
||||
public class PresenterFactory(
|
||||
World world,
|
||||
ComponentFactory componentFactory,
|
||||
PresenterRegistry presenterRegistry,
|
||||
Node sceneRoot)
|
||||
{
|
||||
private readonly World _world = world;
|
||||
private readonly ComponentFactory _componentFactory = componentFactory;
|
||||
private PresenterRegistry _presenterRegistry = presenterRegistry;
|
||||
private readonly Node _sceneRoot = sceneRoot;
|
||||
|
||||
public PresenterData CreateEntityFromArchetype(EntityArchetype archetype, GameCore.Math.Vector3? position = null,
|
||||
GameCore.Math.Vector3? rotation = null, GameCore.Math.Vector3? initialVelocity = null)
|
||||
{
|
||||
var entity = _world.CreateEntity();
|
||||
|
||||
foreach (var resource in archetype.ComponentResources)
|
||||
{
|
||||
var component = _componentFactory.Create(resource);
|
||||
if (component != null) _world.AddComponent(entity, component);
|
||||
}
|
||||
|
||||
var presenterNode = archetype.Scene.Instantiate<Node>();
|
||||
if (presenterNode is not IEntityPresenter presenter)
|
||||
{
|
||||
GD.PrintErr($"Archetype scene '{archetype.ResourcePath}' root does not implement IEntityPresenter!");
|
||||
presenterNode.QueueFree();
|
||||
return default;
|
||||
}
|
||||
|
||||
presenter.CoreEntity = entity;
|
||||
|
||||
var components = InitializePresenterComponents(presenterNode, entity);
|
||||
|
||||
if (position.HasValue && _world.GetComponent<PositionComponent>(entity) is { } posComp)
|
||||
posComp.Position = position.Value;
|
||||
if (rotation.HasValue && _world.GetComponent<RotationComponent>(entity) is { } rotComp)
|
||||
rotComp.Rotation = rotation.Value;
|
||||
if (initialVelocity.HasValue && _world.GetComponent<VelocityComponent>(entity) is { } velComp)
|
||||
velComp.DesiredVelocity = initialVelocity.Value;
|
||||
|
||||
_sceneRoot.AddChild(presenterNode);
|
||||
return new PresenterData(entity, presenter, components);
|
||||
}
|
||||
|
||||
public PresenterData RegisterSceneEntity(Node presenterNode, Array<Resource> componentResources)
|
||||
{
|
||||
var entity = _world.CreateEntity();
|
||||
|
||||
foreach (var resource in componentResources)
|
||||
{
|
||||
var component = _componentFactory.Create(resource);
|
||||
if (component != null) _world.AddComponent(entity, component);
|
||||
}
|
||||
|
||||
if (presenterNode is not IEntityPresenter presenter)
|
||||
{
|
||||
GD.PrintErr($"Scene node '{presenterNode.Name}' does not implement IEntityPresenter!");
|
||||
return default;
|
||||
}
|
||||
|
||||
presenter.CoreEntity = entity;
|
||||
var components = InitializePresenterComponents(presenterNode, entity);
|
||||
return new PresenterData(entity, presenter, components);
|
||||
}
|
||||
|
||||
private List<IPresenterComponent> InitializePresenterComponents(Node presenterNode, Entity entity)
|
||||
{
|
||||
_presenterRegistry.RegisterPresenter(presenterNode, entity);
|
||||
|
||||
var components = new List<IPresenterComponent>();
|
||||
foreach (var child in presenterNode.GetChildren(true))
|
||||
{
|
||||
if (child is IPresenterComponent pComponent)
|
||||
{
|
||||
pComponent.Initialize(entity, _world);
|
||||
components.Add(pComponent);
|
||||
}
|
||||
}
|
||||
if (presenterNode is IPresenterComponent rootComponent)
|
||||
{
|
||||
rootComponent.Initialize(entity, _world);
|
||||
components.Add(rootComponent);
|
||||
}
|
||||
return components;
|
||||
}
|
||||
}
|
||||
1
Code/Factories/PresenterFactory.cs.uid
Normal file
1
Code/Factories/PresenterFactory.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://balunj6u4ptjq
|
||||
Reference in New Issue
Block a user