using Minesweeper.Core; using Minesweeper.ECS.Components; using Unity.Collections; using Unity.Entities; namespace Minesweeper.ECS { public sealed class BoardEcsSyncService : IBoardEcsSyncService { public void SyncBoard(IBoardService boardService) { if (!TryGetEntityManager(out var entityManager)) { return; } ClearCells(entityManager); var boardEntity = GetOrCreateSingleton(entityManager); entityManager.SetComponentData(boardEntity, new BoardConfigComponent { Width = boardService.Width, Height = boardService.Height, MinesCount = boardService.MinesCount }); var archetype = entityManager.CreateArchetype(typeof(CellComponent)); var cells = boardService.GetCells(); for (var i = 0; i < cells.Count; i++) { var cell = cells[i]; var entity = entityManager.CreateEntity(archetype); entityManager.SetComponentData(entity, new CellComponent { X = cell.X, Y = cell.Y, IsMine = ToByte(cell.IsMine), IsOpened = ToByte(cell.IsOpened), IsFlagged = ToByte(cell.IsFlagged), NeighborMines = cell.NeighborMines }); } } public void SyncGameState(GameState state, bool hasFirstClick) { if (!TryGetEntityManager(out var entityManager)) { return; } var stateEntity = GetOrCreateSingleton(entityManager); entityManager.SetComponentData(stateEntity, new GameStateComponent { State = state, HasFirstClick = ToByte(hasFirstClick) }); } private static bool TryGetEntityManager(out EntityManager entityManager) { var world = World.DefaultGameObjectInjectionWorld; if (world == null || !world.IsCreated) { entityManager = default; return false; } entityManager = world.EntityManager; return true; } private static void ClearCells(EntityManager entityManager) { var query = entityManager.CreateEntityQuery(typeof(CellComponent)); entityManager.DestroyEntity(query); query.Dispose(); } private static Entity GetOrCreateSingleton(EntityManager entityManager) where T : unmanaged, IComponentData { var query = entityManager.CreateEntityQuery(typeof(T)); Entity entity; if (query.IsEmptyIgnoreFilter) { entity = entityManager.CreateEntity(typeof(T)); } else { var entities = query.ToEntityArray(Allocator.Temp); entity = entities[0]; for (var i = 1; i < entities.Length; i++) { entityManager.DestroyEntity(entities[i]); } entities.Dispose(); } query.Dispose(); return entity; } private static byte ToByte(bool value) { return value ? (byte)1 : (byte)0; } } }