Руководство для AI-агентов

Если вы используете AI-ассистенты (Claude Code, Cursor, Copilot и др.) со StaticEcs, вы можете предоставить агенту контекст о библиотеке. Эта страница содержит готовые сниппеты.


llms.txt

Укажите вашему агенту на AI-документацию библиотеки:

  • Краткая: https://felid-force-studios.github.io/StaticEcs/llms.txt
  • Полная: https://felid-force-studios.github.io/StaticEcs/llms-full.txt

Сниппет для CLAUDE.md

Если вы используете Claude Code, скопируйте следующий блок в CLAUDE.md вашего проекта. Это даст Claude необходимый контекст для правильного использования StaticEcs.

Для других агентов вставьте это в соответствующие файлы инструкций (.cursorrules, .github/copilot-instructions.md и т.д.).

## StaticEcs ECS Framework

Этот проект использует [StaticEcs](https://github.com/Felid-Force-Studios/StaticEcs) — статический generic ECS-фреймворк для C#. Namespace: `FFS.Libraries.StaticEcs`.

### Паттерн настройки
```csharp
public struct WT : IWorldType { }
public abstract class W : World<WT> { }           // type alias для доступа к миру
public struct GameSystems : ISystemsType { }
public abstract class GameSys : W.Systems<GameSystems> { }
```

### Жизненный цикл мира (строгий порядок)
1. `W.Create(WorldConfig.Default())` — создание мира
2. `W.Types().RegisterAll()` или ручная регистрация `.Component<T>().Tag<T>().Event<T>()` — регистрация ВСЕХ типов (обязательно!)
3. `W.Initialize()` — после этого доступны операции с сущностями
4. Работа: создание сущностей, запуск систем, итерация запросов
5. `W.Destroy()` — очистка

### Критические правила
- ВСЕГДА регистрируйте типы компонентов/тегов/событий/связей между Create() и Initialize(). Используйте `W.Types().RegisterAll()` для авторегистрации всех типов из сборки, или регистрируйте вручную. Незарегистрированные типы вызывают ошибки.
- Entity — 4-байтовый uint-хендл, НЕ постоянная ссылка. НИКОГДА не храните Entity в полях/коллекциях между кадрами. Используйте EntityGID.
- `Add<T>()` без значения идемпотентен (если существует → возвращает ref, без хуков). `Set(value)` ВСЕГДА перезаписывает с циклом OnDelete→OnAdd.
- `Ref<T>()` возвращает ref на компонент. Предполагает наличие компонента — проверяйте `Has<T>()` если не уверены.
- Для компонентов, которые только читаются, используйте `Read<T>()` (возвращает `ref readonly`) вместо `Ref<T>()`, а в делегатах запросов — `in` вместо `ref`.
- Типы фильтров запросов: `All<>` (требовать), `None<>` (исключить), `Any<>` (хотя бы один). Эти фильтры работают и с компонентами, и с тегами. Комбинировать: `And<Filter1, Filter2>` (все должны совпасть) или `Or<Filter1, Filter2>` (хотя бы один).
- Стандартный режим запроса — Strict. НЕ модифицируйте фильтруемые типы у ДРУГИХ сущностей при итерации. Используйте `EntitiesFlexible()` при необходимости.
- При `ForParallel` модифицируйте только текущую сущность. Без структурных изменений.

### Типичные паттерны
```csharp
// Создание сущности с компонентами
var entity = W.NewEntity<Default>().Set(new Position { Value = v }, new Velocity { Value = 1f });

// Итерация запроса (foreach)
foreach (var e in W.Query<All<Position, Velocity>>().Entities()) {
    ref var pos = ref e.Ref<Position>();
    ref readonly var vel = ref e.Read<Velocity>();
    pos.Value += vel.Value;
}

// Итерация запроса (делегат — быстрее, без аллокаций)
W.Query().For(static (ref Position p, in Velocity v) => {
    p.Value += v.Value;
});

// Постоянная ссылка
EntityGID gid = entity.GID;
if (gid.TryUnpack<WT>(out var resolved)) { /* resolved жив */ }

// Теги
entity.Set<IsPlayer>();
if (entity.Has<IsPlayer>()) { ... }

// Мультикомпоненты (список однотипных значений на сущности)
ref var items = ref entity.Add<W.Multi<Item>>();
items.Add(new Item { Id = 1 });
items.Add(new Item { Id = 2 });
foreach (ref var item in items) { item.Weight *= 2f; }

// Отношения (связи между сущностями)
entity.Set(new W.Link<Parent>(parentEntity));           // одиночная связь
ref var children = ref entity.Add<W.Links<Children>>(); // множественная связь
children.TryAdd(childEntity.AsLink<Children>());

// Системы
public struct MoveSystem : ISystem {
    public void Init() { /* вызывается один раз при Initialize */ }
    public void Update() {
        W.Query().For(static (ref Position p, in Velocity v) => {
            p.Value += v.Value;
        });
    }
    public void Destroy() { /* вызывается при Destroy */ }
}
GameSys.Create();
GameSys.Add(new MoveSystem(), order: 0);
GameSys.Initialize();
// В игровом цикле: GameSys.Update();

// Ресурсы
W.SetResource(new GameConfig { ... });
ref var config = ref W.GetResource<GameConfig>();
```

### Полная документация
- Краткая AI-справка: https://felid-force-studios.github.io/StaticEcs/llms.txt
- Полная документация: https://felid-force-studios.github.io/StaticEcs/ru/features.html

This site uses Just the Docs, a documentation theme for Jekyll.