using GameCore.Config;
using GameCore.ECS.Interfaces;
using GameCore.Events;
using GameCore.Events.Interfaces;
using GameCore.Input.Interfaces;
using GameCore.Interaction;
using GameCore.Logging.Interfaces;
using GameCore.Services;
using GameCore.State;
namespace GameCore.ECS;
///
/// The central container for the entire game state.
/// It manages all entities, components, and systems, and orchestrates the main game loop.
/// This class is the primary point of interaction for the Engine/Presentation layer.
///
public class World
{
private readonly Dictionary> _componentsByEntityId = new();
private readonly EventBus _eventBus = new();
private readonly List _systems = [];
public readonly IAudioService AudioService;
public readonly SimulationConfig Config;
public readonly IGameStateService GameState;
public readonly IInputService InputService;
public readonly ILogger Logger;
public readonly IParticleService ParticleService;
public readonly IWorldQuery WorldQuery;
private int _nextEntityId;
public World(IInputService inputService,
IWorldQuery worldQuery,
SimulationConfig config,
ILogger logger,
IAudioService audioService,
IParticleService particleService)
{
AudioService = audioService;
Config = config;
InputService = inputService;
Logger = logger;
ParticleService = particleService;
WorldQuery = worldQuery;
GameState = new GameStateService(this);
}
///
/// Creates a new, unique entity.
///
/// The newly created Entity.
public Entity CreateEntity()
{
var id = _nextEntityId++;
_componentsByEntityId[id] = [];
return new Entity(id);
}
public void DestroyEntity(Entity entity)
{
_componentsByEntityId.Remove(entity.Id);
}
///
/// Adds a component to a given entity.
///
public void AddComponent(Entity entity, IComponent component)
{
_componentsByEntityId[entity.Id].Add(component);
}
public void RemoveComponent(Entity entity) where T : class, IComponent
{
if (!_componentsByEntityId.TryGetValue(entity.Id, out var components)) return;
var componentToRemove = components.OfType().FirstOrDefault();
if (componentToRemove != null) components.Remove(componentToRemove);
}
///
/// Retrieves a specific type of component from an entity.
///
/// The component instance, or null if the entity doesn't have it.
public T? GetComponent(Entity entity) where T : class, IComponent
{
return _componentsByEntityId.TryGetValue(entity.Id, out var components)
? components.OfType().FirstOrDefault()
: null;
}
///
/// Finds all entities that have a specific component type.
///
public IEnumerable GetEntitiesWith() where T : IComponent
{
return from pair in _componentsByEntityId
where pair.Value.Any(c => c is T)
select new Entity(pair.Key);
}
///
/// Registers a system to be run in the game loop.
///
public void RegisterSystem(ISystem system)
{
_systems.Add(system);
}
///
/// Runs a single tick of the game simulation, updating all registered systems.
///
public void Update(float deltaTime)
{
foreach (var system in _systems) system.Update(this, deltaTime);
}
public void PublishEvent(IEvent gameEvent)
{
_eventBus.Publish(gameEvent);
}
public void ProcessEvents()
{
_eventBus.ProcessEvents();
}
public void Subscribe(Action handler) where T : IEvent
{
_eventBus.Subscribe(handler);
}
public void Unsubscribe(Action handler) where T : IEvent
{
_eventBus.Unsubscribe(handler);
}
public Entity? FindEntityByWorldId(string worldId)
{
if (string.IsNullOrEmpty(worldId)) return null;
foreach (var entity in _componentsByEntityId.Keys.Select(id => new Entity(id)))
{
var idComponent = GetComponent(entity);
if (idComponent != null && idComponent.WorldId == worldId)
return entity;
}
return null;
}
}