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(); 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(entity) is { } posComp) posComp.Position = position.Value; if (rotation.HasValue && _world.GetComponent(entity) is { } rotComp) rotComp.Rotation = rotation.Value; if (initialVelocity.HasValue && _world.GetComponent(entity) is { } velComp) velComp.DesiredVelocity = initialVelocity.Value; _sceneRoot.AddChild(presenterNode); return new PresenterData(entity, presenter, components); } public PresenterData RegisterSceneEntity(Node presenterNode, Array 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 InitializePresenterComponents(Node presenterNode, Entity entity) { _presenterRegistry.RegisterPresenter(presenterNode, entity); var components = new List(); 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; } }