using System.Collections.Generic; using CryptonymThunder.Code.Autoloads; using CryptonymThunder.Code.Factories; using CryptonymThunder.Code.Resources; using CryptonymThunder.Code.Services; using GameCore.Attributes; using GameCore.Combat; using GameCore.Config; using GameCore.ECS; using GameCore.ECS.Interfaces; using GameCore.Events; using GameCore.Input; using GameCore.Movement; using Godot; namespace CryptonymThunder.Code.Presenters; [GlobalClass] public partial class GamePresenter : Node { [Export] private ArchetypeDatabase ArchetypesDatabase { get; set; } [Export] private EntityArchetype PlayerArchetype { get; set; } [Export] private SimulationConfigResource SimulationConfig { get; set; } private World _world; private PresenterRegistry _presenterRegistry; private GodotInputService _inputService; private GodotWorldQuery _worldQuery; private PresenterFactory _presenterFactory; private readonly Dictionary> _presenterComponents = new(); private readonly Dictionary _presenters = new(); public override void _Ready() { _presenterRegistry = GetNode("/root/PresenterRegistry"); _inputService = new GodotInputService(); _worldQuery = new GodotWorldQuery(this); var simConfig = new SimulationConfig(); if (SimulationConfig != null) { simConfig.GravityStrength = SimulationConfig.GravityStrength; } _world = new World(_inputService, _worldQuery, simConfig); _presenterFactory = new PresenterFactory(_world, new ComponentFactory(), _presenterRegistry, this); _world.RegisterSystem(new PlayerInputSystem()); _world.RegisterSystem(new RotationSystem()); _world.RegisterSystem(new GroundMovementSystem()); _world.RegisterSystem(new GravitySystem()); _world.RegisterSystem(new JumpSystem()); _world.RegisterSystem(new AttributeSystem()); _world.RegisterSystem(new WeaponSystem()); _world.RegisterSystem(new ProjectileSystem()); _world.RegisterSystem(new ProjectileInitializationSystem(_world)); _world.RegisterSystem(new DamageSystem(_world)); _world.RegisterSystem(new ProjectileCleanupSystem()); _world.RegisterSystem(new DestructionSystem()); _world.Subscribe(OnEntityDied); _world.Subscribe(OnSpawnEntity); RegisterAllSceneEntities(); var playerData = _presenterFactory.CreateEntityFromArchetype(PlayerArchetype); _presenters.Add(playerData.Entity.Id, playerData.Presenter); _presenterComponents.Add(playerData.Entity.Id, playerData.Components); } public override void _Input(InputEvent @event) { _inputService?.HandleInputEvent(@event); } public override void _PhysicsProcess(double delta) { if (_presenters.Count == 0) return; _inputService.Update(); _world.Update((float)delta); _world.ProcessEvents(); foreach (var componentList in _presenterComponents.Values) { foreach (var component in componentList) { component.SyncToPresentation((float)delta); } } foreach (var componentList in _presenterComponents.Values) { foreach (var component in componentList) { component.SyncToCore((float)delta); } } _inputService.LateUpdate(); } private void OnSpawnEntity(SpawnEntityEvent @event) { if (ArchetypesDatabase.Archetypes.TryGetValue(@event.ArchetypeId, out var archetype)) { var presenterData = _presenterFactory.CreateEntityFromArchetype(archetype, @event.Position, @event.Rotation, @event.InitialVelocity); _presenters.Add(presenterData.Entity.Id, presenterData.Presenter); _presenterComponents.Add(presenterData.Entity.Id, presenterData.Components); _world.PublishEvent(new EntitySpawnedEvent(presenterData.Entity, @event.Owner, @event.ArchetypeId)); } } private void OnEntityDied(EntityDiedEvent e) { if (_presenters.Remove(e.Entity.Id, out var presenter)) { _presenterRegistry.UnregisterPresenter(presenter as Node); _presenterComponents.Remove(e.Entity.Id); (presenter as Node)?.QueueFree(); } } private void RegisterAllSceneEntities() { var sceneEntities = GetTree().GetNodesInGroup("SceneEntities"); foreach (var node in sceneEntities) { if (node is SceneEntity sceneEntity) { var parentNode = sceneEntity.GetParent(); if (parentNode != null) { var presenterData = _presenterFactory.RegisterSceneEntity(parentNode, sceneEntity.ComponentResources); _presenters.Add(presenterData.Entity.Id, presenterData.Presenter); _presenterComponents.Add(presenterData.Entity.Id, presenterData.Components); } } } } public Node GetPresenterNode(Entity entity) { if (_presenters.TryGetValue(entity.Id, out var presenter)) { return presenter as Node; } return null; } }