[Add] Field and mine generation

This commit is contained in:
2026-06-06 21:18:10 +07:00
parent 8ed9cc655f
commit 1a6f8901a2
17 changed files with 481 additions and 7 deletions
@@ -0,0 +1,110 @@
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<BoardConfigComponent>(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<GameStateComponent>(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<T>(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;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0ad76f74587f648429ed4e14a39e4d13
@@ -0,0 +1,10 @@
using Minesweeper.Core;
namespace Minesweeper.ECS
{
public interface IBoardEcsSyncService
{
void SyncBoard(IBoardService boardService);
void SyncGameState(GameState state, bool hasFirstClick);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 779db0eb469cc2449bce502b6e46231d