Пишем Third Person Controller на MonoGame. Часть II
Это вторая часть серии туториалов, где мы реализуем Third Person Controller на MonoGame. В этой части мы заменим капсулу персонажа на анимированную модель. И прицепим меч на спину.

Объектно-ориентированный язык программирования
Это вторая часть серии туториалов, где мы реализуем Third Person Controller на MonoGame. В этой части мы заменим капсулу персонажа на анимированную модель. И прицепим меч на спину.

Разрабатывая приложения, мы стараемся не злоупотреблять дублированием кода. Из часто встречающегося кода мы формируем библиотеки, а для их соединения в инфраструктуре ASP.NET Core приложения используем DI-контейнер. Инфраструктура тестирования для ASP.NET Core API, как правило, тоже повторяется, но какие инструменты помогают нам переиспользовать тестовый код?
Разработчики Python решают эту задачу с помощью pytest.fixtures, однако в dotnet-экосистеме (xUnit) хорошего аналога пока нет.
В статье рассмотрим пример, как в несколько строк собрать полноценное интеграционное окружение с изолированной БД, фейковым временем и случайностью, а также как донастроить это окружение для отдельно взятого теста.
Для кого эта статья: для бэкенд-разработчиков (на .NET), технических лидов, QA-инженеров, которые пишут код, и всех, кто устал от бессмысленно повторяющегося кода в тестах.
Если вы пишете на C#, но хотите добавить тестам элегантности Python — добро пожаловать.

Написал это для друга чтобы он не звонил мне с вопросом «почему Telegram не работает».
А теперь звонит с вопросом «когда обновление»... Прогресс)
NetFix - это GUI-приложение для Zapret и TgWsProxy с ПОЛНОЙ автоматизацией. Не просто запуск, оно само скачивает, само настраивает, само следит, само обновляет. Одна кнопка вместо батников, конфигов и консоли.
Что внутри, как это работает и почему там есть даже ритм-игра - читайте далее 👇

Всем доброго времени суток. В этой статье разжуем некоторые проблемы OSDev'а в том виде, в котором его хотят видеть люди.
Обсудим «конструкторы ОС» и все его плюсы и недостатки.

Чуть больше полугода назад состоялся релиз .NET 10. Остались ли дефекты в исходном коде проекта, спустя месяцы после релиза? Постараемся сегодня найти ответ на этот вопрос.

С вами снова Илья Вязников, инженер сопровождения SOFROS. Продолжаю делиться практическими приёмами, которые упрощают жизнь при эксплуатации и доработке интеграций.
Не так давно я рассказывал, как вынести повторяющуюся логику в C# функции, но в любом серьёзном проекте со временем накапливаются не только функции, но и куча параметров: адреса сервисов, таймауты и т.д. Сначала их прописывают прямо в коде, но очень быстро это превращается в проблему.
Сегодня расскажу про глобальные константы — один из полезных инструментов платформы для централизованного хранения таких параметров.
Продолжаем серию про redb.Route — вводная и разбор четырёх in-memory каналов уже вышли. Сегодня не статья серии, а релизная заметка: в 3.0.1 три конкретных изменения в DSL, каждое с боевым примером из демо.
До 3.0.1 глубоко вложенные scope-ы требовали закрывать себя в строго обратном порядке — утомительно и легко ошибиться. Три вещи изменились.
FFI, P/Invoke, EmbeddedResource, DllImportResolver и кроссплатформенная доставка без ручного копирования .dll, .so и .dylib.
Когда .NET-коду нужно вызвать Rust-библиотеку, первый прототип обычно заводится быстро:
Rust собирается как cdylib;
функции экспортируются через extern "C";
C# вызывает их через DllImport;
результат возвращается через указатель.

Мы убрали одну блокировку, чтобы апрувы перестали тормозить. Через несколько недель из‑за этого клиент пробил квартальный бюджет — а наша система этого даже не заметила.
Полгода после MVP, первые крупные клиенты. B2B travel SaaS, конец 2016-го. Компании начали подключать не по 15–20 человек, а по 80–100.
Один из новых клиентов оказался кратно крупнее остальных — финансовый департамент почти на сотню человек с фиксированным квартальным бюджетом на командировки порядка нескольких сотен тысяч рублей. К середине квартала большая часть бюджета уже потрачена, остаток — заметно меньше половины. Два руководителя — в разных городах, в разных браузерах — одновременно открывают форму апрува командировок. Оба видят один и тот же остаток. Один одобряет крупную поездку, другой почти в то же время — ещё одну, сопоставимую по сумме; каждая по отдельности в остаток вписывалась. Оба получают подтверждение. Вместе две поездки пробили лимит — перерасход, которого ни один из руководителей в одиночку не допускал.
Обнаружили через 3–4 часа — когда финансовый менеджер клиента открыл квартальную сводку и позвонил нам.

Прошлая статья была обзорной — что такое redb.Route, зачем нам понадобился свой Apache Camel под .NET, как выглядит боевой маршрут. Если не читали, коротко: это fluent C# DSL для интеграции — 22 коннектора (~30 URI-схем, если считать https/wss/es-варианты), ~30 паттернов EIP нативно через 41 процессор, 8 in-process компонентов, компилируемый expression-движок. Сегодня заходим внутрь. Не список фич, а рабочий разбор.
Серия будет длинной, поэтому сразу скажу, что и в каком порядке:

Создаю собственный DSL на C#: рассказываю о том, как написать парсер, и как его оптимизировать. Так же покажу как работает обещанный DFA.

У вас не 5 микросервисов — у вас десятки. Бэкенд, который рос три года: монолит, расколотый на куски, GPS-фид от автопарка, мобильное приложение водителя, веб-кабинет диспетчера, интеграции с SAP / 1С / регуляторами / маркетплейсами, отдельный SMTP-воркер, отдельный PDF-генератор, отдельный шедулер ночных пересчётов. Между ними — Kafka (несколько кластеров, по топику на домен), RabbitMQ (RPC + pub/sub + DLQ), Redis (кэш, last-known-state, pub/sub-каналы), пара HTTP-эндпоинтов наружу, SFTP с поставщиком, SQL-polling outbox-таблицы старого монолита, MQTT с трекеров, IBM MQ для одного древнего банковского контура, SignalR-хабы для real-time-дашбордов. На каждом стыке — свой ретрай, свой DLQ (или нет DLQ), своя сериализация, свои метрики (или нет метрик), своя бойлерплейт-обвязка из консьюмеров и try/catch.
Каждый из этих стыков живёт своей жизнью в Program.cs соответствующего сервиса. Каждый — это hand-rolled цикл:

Каждый разработчик на .NET сталкивался с этим. Всё работает быстро, но иногда случается внезапный фриз. Игра проседает с 60 до 30 FPS на секунду. Сервис отвечает на запрос 100 мс вместо обычных 10. UI дёргается.
Виновник — Garbage Collector.
Когда GC решает собрать мусор, он останавливает все потоки приложения (Stop-The-World). Для игр и real-time сервисов это катастрофа.
Стандартные коллекции .NET создают мусор везде:

В real-time играх и серверах часто возникает задача: из N объектов нужно выбрать K лучших, чтобы обновить их в этом кадре.

Каждый игровой инженер сталкивался с этим. У вас есть 16.67 мс на кадр (60 FPS). В сцене 10 000+ объектов: враги, частицы, тени, декали, постыффекты. Нужно решить: на что потратить бюджет, чтобы игрок видел самое важное в максимальном качестве, а FPS не проседал?
Типичные подходы и их недостатки
1. Дистанционный LOD (расстояние до камеры)

Типизированное хранилище для .NET поверх Postgres и MSSQL. C#-класс как схема — без миграций, без Include, с полным LINQ. Работает в проде.

Практически в каждом высоконагруженном .NET-проекте рано или поздно появляется один и тот же паттерн:
Есть коллекция данных.
Для каждого элемента нужно выполнить дорогую операцию.
Например:
вычислить хэш;

Не так давно, я писал, о том как автоматизировать повторную обработку сообщений из архива в DATAREON Platform.
Было несколько вопросов и уточнений, поэтому хочу дополнительно разобрать код C# для повторной обработки.
Для ЛЛ: Полный алгоритм с комментариями в конце поста

Рассказываю, как написал кроссплатформенную .NET-библиотеку для глобального перехвата клавиатуры и мыши. Под капотом: WH_KEYBOARD_LL на Windows, CGEventTap на macOS и polling через XQueryKeymap на Linux. Один интерфейс, три реализации, ноль внешних зависимостей.

Представьте, что у вас есть многослойный пайплайн обработки данных.
Ширина слоя — 5000 узлов. Количество слоёв — 60. Общее число узлов — 300 000.
Каждую секунду приходит 10 новых событий (изменений на входе). Наивный подход — пересчитать всё с нуля — будет перебирать все 300 000 узлов на каждое обновление. При 10 обновлениях в секунду это 3 млн вычислений узлов в секунду. А если ширина слоя 100 000 и слоёв 100? Получаем 10 млн узлов на пересчёт. Компьютер не справляется.