using GameCore.ECS; using GameCore.ECS.Interfaces; using GameCore.Events; using GameCore.Input; using GameCore.Player; namespace GameCore.Interaction; public class InteractionSystem(float interactionRange) : ISystem { public void Update(World world, float deltaTime) { var playerEntities = world.GetEntitiesWith(); var players = playerEntities.ToList(); if (!players.Any()) return; var player = players.First(); var input = world.GetComponent(player); if (input == null) return; world.RemoveComponent(player); var from = input.MuzzlePosition; var to = from + input.MuzzleDirection * interactionRange; var hit = world.WorldQuery.Raycast(from, to, player); if (hit.DidHit && hit.HitEntity.HasValue) { var door = world.GetComponent(hit.HitEntity.Value); if (door != null) { world.AddComponent(player, new IsLookingAtInteractableComponent(hit.HitEntity.Value)); if (input.IsInteracting) TryInteractWithDoor(world, player, hit.HitEntity.Value, door); } } } private void TryInteractWithDoor(World world, Entity interactor, Entity doorEntity, DoorComponent door) { switch (door.CurrentState) { case DoorComponent.DoorState.Locked: if (CheckRequirements(world, interactor, door)) { world.Logger.Info($"Door {doorEntity.Id} requirements met. Unlocking door."); door.CurrentState = DoorComponent.DoorState.Opening; if (door.IsOneTimeUnlock) door.Requirements.Clear(); world.PublishEvent(new DoorStateChangedEvent(doorEntity, door.CurrentState)); } else { world.Logger.Info($"Door {doorEntity.Id} requirements not met. Cannot unlock door."); world.PublishEvent(new DoorLockedEvent(doorEntity, interactor)); } break; case DoorComponent.DoorState.Closed: door.CurrentState = DoorComponent.DoorState.Opening; world.PublishEvent(new DoorStateChangedEvent(doorEntity, door.CurrentState)); break; case DoorComponent.DoorState.Open: door.CurrentState = DoorComponent.DoorState.Closing; world.PublishEvent(new DoorStateChangedEvent(doorEntity, door.CurrentState)); break; } } private bool CheckRequirements(World world, Entity interactor, DoorComponent door) { foreach (var req in door.Requirements) if (!req.IsMet(interactor, world)) return false; foreach (var req in door.Requirements) req.ApplySideEffects(interactor, world); return true; } }