[Fix] ECS
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Minesweeper.Core;
|
||||
using Minesweeper.ECS.Components;
|
||||
using Unity.Collections;
|
||||
@@ -7,6 +8,10 @@ namespace Minesweeper.ECS
|
||||
{
|
||||
public sealed class BoardEcsSyncService : IBoardEcsSyncService
|
||||
{
|
||||
private readonly Dictionary<int, Entity> cellsByIndex = new Dictionary<int, Entity>();
|
||||
private int syncedWidth;
|
||||
private int syncedHeight;
|
||||
|
||||
public void ClearBoard()
|
||||
{
|
||||
if (!TryGetEntityManager(out var entityManager))
|
||||
@@ -15,6 +20,9 @@ namespace Minesweeper.ECS
|
||||
}
|
||||
|
||||
ClearCells(entityManager);
|
||||
cellsByIndex.Clear();
|
||||
syncedWidth = 0;
|
||||
syncedHeight = 0;
|
||||
}
|
||||
|
||||
public void SyncBoard(IBoardService boardService)
|
||||
@@ -24,14 +32,27 @@ namespace Minesweeper.ECS
|
||||
return;
|
||||
}
|
||||
|
||||
ClearCells(entityManager);
|
||||
if (syncedWidth != boardService.Width || syncedHeight != boardService.Height || cellsByIndex.Count != boardService.Width * boardService.Height)
|
||||
{
|
||||
ClearCells(entityManager);
|
||||
cellsByIndex.Clear();
|
||||
syncedWidth = boardService.Width;
|
||||
syncedHeight = boardService.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearChangedTags(entityManager);
|
||||
}
|
||||
|
||||
var boardEntity = GetOrCreateSingleton<BoardConfigComponent>(entityManager);
|
||||
entityManager.SetComponentData(boardEntity, new BoardConfigComponent
|
||||
{
|
||||
Width = boardService.Width,
|
||||
Height = boardService.Height,
|
||||
MinesCount = boardService.MinesCount
|
||||
MinesCount = boardService.MinesCount,
|
||||
OpenedSafeCellsCount = boardService.OpenedSafeCellsCount,
|
||||
FlaggedCellsCount = boardService.FlaggedCellsCount,
|
||||
IsGenerated = ToByte(boardService.IsGenerated)
|
||||
});
|
||||
|
||||
var archetype = entityManager.CreateArchetype(typeof(CellComponent));
|
||||
@@ -39,16 +60,45 @@ namespace Minesweeper.ECS
|
||||
for (var i = 0; i < cells.Count; i++)
|
||||
{
|
||||
var cell = cells[i];
|
||||
var entity = entityManager.CreateEntity(archetype);
|
||||
entityManager.SetComponentData(entity, new CellComponent
|
||||
var index = ToIndex(cell.X, cell.Y, boardService.Width);
|
||||
if (!cellsByIndex.TryGetValue(index, out var entity) || !entityManager.Exists(entity))
|
||||
{
|
||||
X = cell.X,
|
||||
Y = cell.Y,
|
||||
IsMine = ToByte(cell.IsMine),
|
||||
IsOpened = ToByte(cell.IsOpened),
|
||||
IsFlagged = ToByte(cell.IsFlagged),
|
||||
NeighborMines = cell.NeighborMines
|
||||
});
|
||||
entity = entityManager.CreateEntity(archetype);
|
||||
cellsByIndex[index] = entity;
|
||||
}
|
||||
|
||||
SetCell(entityManager, entity, cell, boardService.Width, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SyncCells(IReadOnlyList<BoardCellData> cells, IBoardService boardService)
|
||||
{
|
||||
if (cells == null || cells.Count == 0 || !TryGetEntityManager(out var entityManager))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var boardEntity = GetOrCreateSingleton<BoardConfigComponent>(entityManager);
|
||||
entityManager.SetComponentData(boardEntity, new BoardConfigComponent
|
||||
{
|
||||
Width = boardService.Width,
|
||||
Height = boardService.Height,
|
||||
MinesCount = boardService.MinesCount,
|
||||
OpenedSafeCellsCount = boardService.OpenedSafeCellsCount,
|
||||
FlaggedCellsCount = boardService.FlaggedCellsCount,
|
||||
IsGenerated = ToByte(boardService.IsGenerated)
|
||||
});
|
||||
|
||||
ClearChangedTags(entityManager);
|
||||
|
||||
for (var i = 0; i < cells.Count; i++)
|
||||
{
|
||||
var cell = cells[i];
|
||||
var index = ToIndex(cell.X, cell.Y, boardService.Width);
|
||||
if (cellsByIndex.TryGetValue(index, out var entity) && entityManager.Exists(entity))
|
||||
{
|
||||
SetCell(entityManager, entity, cell, boardService.Width, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +137,37 @@ namespace Minesweeper.ECS
|
||||
query.Dispose();
|
||||
}
|
||||
|
||||
private static void ClearChangedTags(EntityManager entityManager)
|
||||
{
|
||||
var query = entityManager.CreateEntityQuery(typeof(CellChangedTag));
|
||||
entityManager.RemoveComponent<CellChangedTag>(query);
|
||||
query.Dispose();
|
||||
}
|
||||
|
||||
private static void SetCell(EntityManager entityManager, Entity entity, BoardCellData cell, int width, bool markChanged)
|
||||
{
|
||||
entityManager.SetComponentData(entity, new CellComponent
|
||||
{
|
||||
X = cell.X,
|
||||
Y = cell.Y,
|
||||
Index = ToIndex(cell.X, cell.Y, width),
|
||||
IsMine = ToByte(cell.IsMine),
|
||||
IsOpened = ToByte(cell.IsOpened),
|
||||
IsFlagged = ToByte(cell.IsFlagged),
|
||||
NeighborMines = cell.NeighborMines
|
||||
});
|
||||
|
||||
if (markChanged && !entityManager.HasComponent<CellChangedTag>(entity))
|
||||
{
|
||||
entityManager.AddComponent<CellChangedTag>(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private static int ToIndex(int x, int y, int width)
|
||||
{
|
||||
return y * width + x;
|
||||
}
|
||||
|
||||
private static Entity GetOrCreateSingleton<T>(EntityManager entityManager) where T : unmanaged, IComponentData
|
||||
{
|
||||
var query = entityManager.CreateEntityQuery(typeof(T));
|
||||
|
||||
@@ -7,5 +7,8 @@ namespace Minesweeper.ECS.Components
|
||||
public int Width;
|
||||
public int Height;
|
||||
public int MinesCount;
|
||||
public int OpenedSafeCellsCount;
|
||||
public int FlaggedCellsCount;
|
||||
public byte IsGenerated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Minesweeper.ECS.Components
|
||||
{
|
||||
public struct CellChangedTag : IComponentData
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5702c8f40c71e7444a70e7aa73d8a9db
|
||||
@@ -6,9 +6,11 @@ namespace Minesweeper.ECS.Components
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
public int Index;
|
||||
public byte IsMine;
|
||||
public byte IsOpened;
|
||||
public byte IsFlagged;
|
||||
public int NeighborMines;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Minesweeper.Core;
|
||||
|
||||
namespace Minesweeper.ECS
|
||||
@@ -6,6 +7,7 @@ namespace Minesweeper.ECS
|
||||
{
|
||||
void ClearBoard();
|
||||
void SyncBoard(IBoardService boardService);
|
||||
void SyncCells(IReadOnlyList<BoardCellData> cells, IBoardService boardService);
|
||||
void SyncGameState(GameState state, bool hasFirstClick);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user