using System; using System.Collections.Generic; using System.Linq; using CryptonymThunder.Code.Resources; using GameCore.Attributes; using GameCore.Combat; using GameCore.Combat.Interfaces; using GameCore.ECS.Interfaces; using GameCore.Input; using GameCore.Interaction; using GameCore.Inventory; using GameCore.Logic; using GameCore.Movement; using GameCore.Physics; using GameCore.Player; using Godot; namespace CryptonymThunder.Code.Factories; public class ComponentFactory { private readonly Dictionary> _factories = new(); private readonly EffectFactory _effectFactory; private readonly InteractionRequirementFactory _requirementFactory; private readonly TriggerActionFactory _triggerActionFactory; public ComponentFactory(EffectFactory effectFactory, InteractionRequirementFactory requirementFactory, TriggerActionFactory triggerActionFactory) { _effectFactory = effectFactory; _requirementFactory = requirementFactory; _triggerActionFactory = triggerActionFactory; Register(CreateAttributeComponent); Register(CreateWeaponComponent); Register(CreateProjectileComponent); Register(_ => new PositionComponent()); Register(_ => new VelocityComponent()); Register(_ => new InputStateComponent()); Register(_ => new PlayerComponent()); Register(_ => new RotationComponent()); Register(_ => new CharacterStateComponent()); Register(_ => new InventoryComponent()); Register(CreatePickupComponent); Register(_ => new EquipmentComponent()); Register(CreateDoorComponent); Register(res => new WorldIdComponent(res.WorldId)); Register(CreateButtonComponent); Register(CreateLogicSequenceComponent); } public IComponent Create(Resource resource) { return _factories.TryGetValue(resource.GetType(), out var factory) ? factory(resource) : null; } private void Register(Func 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 fireCosts = weaponData.FireCosts .Select(_effectFactory.Create) .OfType() .ToList(); var onFireEffects = weaponData.OnFireEffects.Select(_effectFactory.Create).ToList(); var onHitEffects = weaponData.OnHitEffects.Select(_effectFactory.Create).ToList(); return new WeaponComponent { FireRate = resource.WeaponData.FireRate, FireCosts = fireCosts, OnFireEffects = onFireEffects, OnHitEffects = onHitEffects, }; } private ProjectileComponent CreateProjectileComponent(ProjectileComponentResource resource) { return new ProjectileComponent { Lifetime = resource.Lifetime, }; } private PickupComponent CreatePickupComponent(PickupComponentResource resource) { var onAcquireEffects = resource.OnAcquireEffects .Select(_effectFactory.Create) .ToList(); return new PickupComponent { ItemId = resource.ItemId, Quantity = resource.Quantity, IsInstantUse = resource.IsInstantUse, OnAcquireEffects = onAcquireEffects, }; } private DoorComponent CreateDoorComponent(DoorComponentResource resource) { var component = new DoorComponent { CurrentState = resource.InitialState, IsOneTimeUnlock = resource.IsOneTimeUnlock, OpenSpeed = resource.OpenSpeed, }; foreach (var reqResource in resource.Requirements) { var requirement = _requirementFactory.Create(reqResource); if (requirement != null) { component.Requirements.Add(requirement); } } return component; } private ButtonComponent CreateButtonComponent(ButtonComponentResource resource) { var component = new ButtonComponent { ChannelId = resource.ChannelId, IsToggle = resource.IsToggle, IsOneTimeUse = resource.IsOneTimeUse, IsPressed = false, HasBeenUsed = false, }; foreach (var reqResource in resource.Requirements) { var requirement = _requirementFactory.Create(reqResource); if (requirement != null) { component.Requirements.Add(requirement); } } return component; } private LogicSequenceComponent CreateLogicSequenceComponent(LogicSequenceComponentResource resource) { var component = new LogicSequenceComponent { RequiredChannels = resource.RequiredChannels.ToList(), IsOneTimeTrigger = resource.IsOneTimeTrigger, }; foreach (var actionResource in resource.OnActivateActions) { var action = _triggerActionFactory.Create(actionResource); if (action != null) { component.OnActivateActions.Add(action); } } foreach (var actionResource in resource.OnDeactivateActions) { var action = _triggerActionFactory.Create(actionResource); if (action != null) { component.OnDeactivateActions.Add(action); } } return component; } }