Серия «Ragnarok Online»

73

Ragnarok Online на Godot + Python. Пустил первых игроков — теперь пишем квесты⁠⁠

Серия Ragnarok Online

В прошлом посте я рассказывал, как собираю свой Ragnarok Online на Godot и Python с помощью нейросетей. Там были конвертеры старых корейских форматов, сетевой протокол, поринги и попытки заставить Python выдерживать населённый мир.

Спасибо всем, кто прочитал и написал. В комментариях спрашивали, где поиграть. Пришлось дать людям клиент и посмотреть, что получится.

Если кратко, то случился деплой.

Сервер теперь живёт на отдельной виртуальной машине, у проекта есть адрес zeroro.ru, а у сообщества — форум. Клиенты лежат на странице скачивания. Пока это ранний тест. Ошибок хватает, и я постоянно бегаю по миру, выясняя, что опять сломалось. Так что если мимо пронеслась взмыленная зёпа без привет/пока, скорее всего, это я спешу что-то тестировать или исправлять.


Windows не пустила дальше запуска

В комментариях @Fymka попробовал запустить игру на Windows и получил ошибку про SSE4.2. Выясняли конфигурацию, переписывались, пересобирали клиент. Он скачал заново, ошибка осталась.

Под Wine у меня всё запускалось. Только @Fymka от этого было не легче.

В итоге для Windows подготовил две сборки: основную x64 и дополнительную x86 с SSE2, без требования SSE4.2. На странице загрузки они находятся в одной карточке; на кнопках прямо написана архитектура.

Есть и нативная сборка macOS — универсальное приложение для Intel и Apple Silicon. Правда, её не тестировал: мне не на чем. Есть тут лица с нетрадиционным выбором техники, готовые помочь протестировать клиент?

Видеокарта и драйверы всё равно должны подходить под требования Godot. А заработало ли в итоге у @Fymka, я пока не знаю (эй, отпишись!).

Там же всплыла ещё одна неприятность: человек хотел сообщить об ошибке, а форма отправки сама отвечала ошибкой. Багрепорт на багрепорт. Приехали.

Ты родился! Что дальше?

Параллельно я сел проходить начало игры обычным персонажем, KittyCat. Нейросеть смотрела сохранённые скриншоты, проверяла текущий этап задания и помогала разбирать проблемы.

И почти сразу упёрся в вопрос: куда идти?

Каюта и журнал задания: сначала ещё надо понять, где выход

Каюта и журнал задания: сначала ещё надо понять, где выход

Задание уже взято, только я об этом не знаю. В журнале написано, что надо попасть в академию. Осталось догадаться открыть журнал. Но сначала нужно найти выход из каюты, потом выход с корабля, потом ещё один корабль. Человек, который делает этот маршрут впервые, не обязан узнавать двери по старой памяти.

Добавили в тестовую версию маячки на мини-карте и большой карте. Они показывают ближайший нужный выход или NPC, а по мере прохождения меняются.

Потом я спросил: а если пойти назад? Вернулся в каюту, поднялся на другой этаж, заблудился по дороге. Маячки нужны и там. Этот маршрут тоже проверяем.

Собрали добычу — карта показывает путь к кораблю обратно в академию

Собрали добычу — карта показывает путь к кораблю обратно в академию

На скриншотах нашлось ещё весёлое. Маячок правильно указывает на преподавателя в академии, а длинный текст задания всё ещё объясняет выход из каюты. Или предметы уже собраны, а описание продолжает предлагать их собирать.

Теперь сверяем и карту, и текст задания. А то одна подсказка отправляет к преподавателю, другая обратно в каюту.

А спросить ещё раз можно?

Регистратор выдал нож и больше ничего полезного не говорил. А я мог случайно закрыть диалог. Или прочитать и через минуту забыть, к кому он меня отправлял. Снова подошёл, а спросить дорогу уже нельзя.

Нож уже в инвентаре. Теперь бы ещё вспомнить, к кому с ним идти

Нож уже в инвентаре. Теперь бы ещё вспомнить, к кому с ним идти

Поправили локально: при повторном разговоре NPC напоминают следующий шаг. Лекарь объясняет здоровье и лечение, Субино — экипировку и бой, Kafra — сохранение и хранилище.

Мы прошли практику: отправились на остров, собрали три Jellopy, вернулись, отдали добычу, посетили Kafra и закончили курс. Смотрели на каждом этапе, что говорит журнал и куда указывает карта.

Первый бой на острове новичков. Поринг уже плюхнулся, остальные пока ждут

Первый бой на острове новичков. Поринг уже плюхнулся, остальные пока ждут

На выходе KittyCat получила выпускные 100 zeny, задание закрылось, дверь выпустила её в Излюд. Из этих скриншотов собираем пошаговую инструкцию для форума. Пока проходили, заодно выловили ошибки в подсказках.

Kafra объясняет сохранение и хранилище, затем отправляет за выпускной наградой

Kafra объясняет сохранение и хранилище, затем отправляет за выпускной наградой

KittyCat после выпуска из академии

KittyCat после выпуска из академии

Для тех, кто знает RO наизусть, предусмотрели пропуск курса у Регистратора. Без выпускной награды, зато без обязательной лекции при создании очередного персонажа.

В комментариях спрашивали про долгую прокачку. Начинаю с первых десяти Job.

После выпуска моя KittyCat оказалась третьего базового и второго профессионального уровня. Академия закончилась, а до первой профессии ещё нужно дорасти.

Сейчас переделываю задания после академии: хочу довести новичка до Job 10 через путешествие по городам. Сначала знакомство с городской Kafra и магазинами Излюда — покупать товары для выполнения заданий не требуется. Затем Проводник предлагает два заказа на добычу, и у каждого есть альтернатива для тех, кто пока не хочет драться.

Первый заказ — пять Jellopy и два яблока с порингов. Вместо охоты можно отнести посылку северной Kafra Пронтеры, у дороги к замку. Второй — десять Clover и три морковки с лунатиков. Его альтернатива — доставка центральной Kafra Пайона. Добычу разрешено получить от других игроков. Доставки сейчас переделываем: Проводник будет выдавать посылку отдельным предметом, который нужно принести адресату.

На каждой развилке награда одинаковая для обоих способов, но получить её можно только один раз. Можно выбрать охоту в первом заказе и доставку во втором — или наоборот. До сдачи разрешено передумать и поменять вариант у Проводника.

Между городами придётся идти через поля с монстрами. Можно обойтись без платных телепортов Kafra, но смотреть по сторонам всё равно надо.

Если Job 10 ещё не достигнут, после второго заказа маршрут продолжается в Гефене: Kafra у южных ворот рассказывает о жизни курьера. Дальше — центральная Kafra Морока, разговор о весе сумки и хранении лишних вещей. Открывать платный склад ради задания не нужно. Завершает путешествие аудиенция у короля Рун-Мидгарда в замке Пронтеры — там новичка благодарят за помощь городам и выдают последнюю награду.

Пишу им разговоры. Например, гефенскую Kafra вчера спросили, можно ли доставить Fire Bolt в закрытом конверте. Пришлось объяснять, что после такого письма остаётся только адрес. А в Мороке перед походом к королю советуют стряхнуть песок с сапог: дворцовые ковры тоже чья-то работа.

Награды посчитали под Job 10: девять наград за прохождение цепочки, всего 570 Base EXP и 1151 Job EXP. Для персонажа с нуля это Base 8 и Job 10. Если десятый Job получен раньше, журнал переводит к выбору профессии, а оставшиеся награды не выдаются.

В журнале будут оба счётчика: сколько собрано Jellopy и сколько яблок. Маячок поведёт сдавать заказ, когда хватит всего. Отдельно проверяем сдачу: если яблок мало, Jellopy забирать нельзя. И получить награду второй раз повторным разговором тоже нельзя. В базе списание предметов, опыт и новый этап сохраняются вместе.

После Job 10 Проводник объясняет Basic Skill и показывает дорогу к выбранной гильдии. Очки за игрока не распределяем, профессию автоматически не выдаём. Условия и экзамены гильдии остаются отдельным этапом: например, будущему Магу ещё потребуется Base 10, а эта цепочка сама по себе его не гарантирует.

Всё это сейчас переделывается и проверяется локально. На боевом сервере готовую цепочку пока не ищите. До старших уровней я с этими квестами тоже ещё не добрался.

Зачем тогда свой клиент?

Меня об этом спрашивали под первым постом. Покажу на часах и чате: их уже можно пощупать в клиенте.

Часы для тех, кто играет на полный экран

В полном экране часов на панели задач не видно. Ради них сворачивать игру неудобно, поэтому сделали свои. Показывают время компьютера игрока, в 24-часовом формате, с секундами. Навёл мышь, увидел полную дату.

Включаются через Alt+T или в настройках: «Интерфейс» → «Панели» → «Часы». Их можно перетащить мышью туда, где они не заслоняют игру; положение и выбранный вид сохраняются.

Есть три размера:

  • Большие: Поринг с настоящим стрелочным циферблатом и цифровым временем под ним.

  • Стандартные: Поринг с табличкой, на которой время и дата.

  • Мини: маленький Поринг и узкая плашка со временем, если хочется оставить больше места для самой игры.

Три размера часов и все одиннадцать вариантов оформления из клиента

Три размера часов и все одиннадцать вариантов оформления из клиента

Всем доступны розовый Поринг, зелёный Попоринг и жёлтый Дропс. На аккаунте можно открыть ещё восемь оформлений: Девилинг, Ангелинг, Мастеринг, Гостринг, Санта, Металинг, Марин и Магмаринг. У кого крылышки, у кого корона, у кого новогодний колпак. Для картинки я собрал их все, включая ещё закрытые для нового аккаунта.

Рожки или нимб у часов на характеристики персонажа не влияют. Просто мне нравятся поринги.

Чат, в котором разговор не тонет в сообщениях о добыче

На охоте чат легко превращается в непрерывный отчёт: урон, опыт, предметы, системные сообщения. Где-то между ними напарник написал, куда идти. Хорошо бы прочитать это до того, как группа ушла в другую сторону.

В клиенте можно завести свои вкладки и отфильтровать сообщения. Например, оставить разговор группы и личные сообщения в одной вкладке, а урон, опыт и добычу — в другой. Каждой можно дать название, выбрать цветной значок и настроить, какие новые сообщения считать для уведомления.

У вкладки есть и канал отправки: для «Группы» можно выбрать групповой чат. В строке ввода есть отдельный переключатель «Всем / Группа», чтобы было видно, кому ты сейчас пишешь.

Реальный интерфейс чата: отдельная вкладка группы и настройки цветов. Сообщения демонстрационные

Реальный интерфейс чата: отдельная вкладка группы и настройки цветов. Сообщения демонстрационные

Шрифт, прозрачность фона и цвета сообщений настраиваются. Можно включить время возле строк и подсветку своего имени. На большом мониторе можно увеличить текст; на светлой карте — сделать фон плотнее. Окно двигается и растягивается, а замок фиксирует его, чтобы случайно не утащить мышью. Положение и настройки сохраняются.

Для личных сообщений есть поле «Кому» и список недавних собеседников. Стрелки вверх и вниз возвращают ранее набранные сообщения. Журнал выбранной вкладки можно сохранить в TXT или HTML — например, чтобы приложить понятную историю к багрепорту.

Заодно разбирались с фокусом ввода: написал сообщение, захотел продолжить играть, а клавиши всё ещё забирает чат. Сейчас Enter в пустой строке или Esc снимают фокус, щелчок по миру тоже возвращает управление игре. Иначе жмёшь клавишу умения, а пишешь букву в чат.

В планах интерфейса — показать вещь прямо в чате

В бэклоге, в группе «Доработки», есть B-121 «Ссылки на предметы в чате». Ещё не реализовано.

Хочу сделать так: перетаскиваешь вещь из инвентаря в строку сообщения — появляется ссылка [Название вещи]. Отправляешь её в общий, групповой или личный чат. Другой игрок нажимает и видит описание именно этого экземпляра: характеристики, заточку, вставленные карты и опознание.

Нашёл нож, спрашиваешь группу «кому пригодится?», и все могут посмотреть, что за нож, с какими картами и заточкой. Не надо переписывать характеристики руками или делать скриншот. Сам предмет при этом остаётся у тебя в сумке.

Что сохраняем в самой игре

Рейты у нас Х1/Х1/Х1: базовый опыт, профессиональный опыт и дроп. Крыльев с характеристиками не планирую. Из кастомного хочу делать косметику и удобства в интерфейсе.

У квестов фиксированная награда опытом, серверный множитель ради них не меняем.

Что дальше

Сначала закончу путь после академии. Нужно пройти обе ветки, проверить выдачу посылок, возвраты на старые карты и перезаходы. Потом решать, готово ли это к выпуску. Пока я сам на этом маршруте нахожу, что поправить.

В клиенте хочу заняться ссылками на вещи и обновлениями: скачивать весь большой пакет ради небольшой правки надоедает. Окна, подсказки и управление тоже будем поправлять по вашим жалобам. Проверка под Wine уже показала, что моей машины для тестирования маловато.

После первых десяти Job хочется продолжить задания. В бэклоге лежат доски объявлений и ежедневные поручения: добыча, поездки между городами, помощь NPC. С наградами ещё надо разбираться. Дальше интересуют групповые приключения, боссы, торговые лавки и аукцион. За всё сразу браться не буду, сроков пока нет.

Есть и работа с сервером: научить сервисы перечитывать конфигурацию и сделать обновления менее болезненными для тех, кто в этот момент играет. Игрок уже добрался до поринга, не хочется выкидывать его ради очередной правки.

О проблемах не забывайте написать через форму на сайте или на форуме. Не держи в себе, пиши. Я люблю вас читать :). Особенно полезно знать, где вы впервые застряли: на установке, в меню, на выходе из каюты или уже перед первым порингом.

А от тех, кто играл давно, интересно услышать: что стоило бы объяснить новичку в первые полчаса, чтобы дальше он уже мог отправиться в приключение сам? И что бы вы поменяли или дополнили в интерфейсе?

Поринги передают привет. И требуют сначала разобраться с дверями.

@ares7782, @CensorAC, @wakuorin — просили пнуть, вот пожалуйста. Пинок доставлен, урон нулевой, ссылка на клиент выше :)

@Dragonslayer666, ты просил написать, где взять клиент. Тебе тоже повестка в Пронтеру!

Показать полностью 8
262

Пишу свой Ragnarok Online. На Godot + Python. С нейросетью⁠⁠

Серия Ragnarok Online

Помните Пронтеру? Фонтан посреди площади, толпа новичков в одинаковых рубашках, торговцы с тележками, кто-то орёт в чат «куплю Jellopy», а в ушах крутится та самая музыка. Для многих Ragnarok Online — это первая MMO, первые друзья в сети и первые бессонные ночи на полях за Порингами.

Я очень долго хотел сделать «свой РО». Не очередной приватный сервер на готовом движке, а игру с нуля: свой сервер, свой клиент, своя база. И вот в этом году я наконец за неё взялся — в паре с нейросетью (Claude Code). Рассказываю, что получилось, как это устроено и куда мы движемся.

Пронтера, площадь у фонтана. Все персонажи вокруг — боты, которых нейросеть запустила для съёмки

Пронтера, площадь у фонтана. Все персонажи вокруг — боты, которых нейросеть запустила для съёмки

Пронтера сверху

Пронтера сверху


Немного цифр для затравки

  • 223 версии игры. Причём больше 200 из них — за последние две недели, когда проект по-настоящему разогнался.

  • 100 локаций: Пронтера, Излюд, Альберта, Гефен, Морок, Пайон, остров новичков, академия, поля, Канализация, Лабиринт, Пайонская пещера, башня и подземелье Гефена, пирамиды, леса Пайона, пустыня Сограт, аббатство Св. Капитолины, гильдейские земли…

  • 160 видов монстров живут на картах — от Поринга до Осириса и Эддги.

  • Все пять первых профессий (Мечник, Маг, Лучник, Вор, Послушник, Торговец — ладно, шесть) с экзаменами по оригинальным сценариям и навыками, включая квестовые.

  • ~68 тысяч строк Python, ~75 тысяч строк GDScript и ~18 тысяч строк Lua.

  • Больше 3 300 автотестов, покрытие серверного кода — 100%. Без этого с нейросетью никак, но об этом ниже.


Из чего это сделано

Если коротко — три кита:

Сервер — Python 3.14. Асинхронный (asyncio), общается с клиентом по WebSocket. Да, Python для MMO-сервера — это немного дерзко, все ждут C++. Но для мира в духе РО, где логика «клеточная», а не физическая, его хватает с запасом (цифры будут дальше).

Клиент — Godot 4.8. Бесплатный движок с открытым кодом, на нём собирается игра под Windows, Linux, macOS и даже в браузер.

База — PostgreSQL. Персонажи, инвентарь, предметы, монстры, их дроп.

Сервер - авторитет: всё, что важно, считает он — куда ты пошёл, попал ли по монстру, что выпало, сколько у тебя зени. Клиент только рисует и плавно доводит персонажей до точки, которую сказал сервер. Так что «накрутить себе Валькирию в Cheat Engine» не выйдет.

Общаются они бинарным протоколом на MessagePack: каждое сообщение — пара байт заголовка и упакованные данные. Самые частые пакеты (шаг персонажа, выбор цели) упакованы ещё плотнее, вручную. Чтобы клиент и сервер никогда не разошлись в понимании протокола, сервер генерирует эталонные «векторы» — набор пакетов байт-в-байт, — а клиент в тестах обязан разобрать и собрать их ровно так же. Поменял пакет и забыл про клиент — тесты сразу краснеют.

А игровые данные — в Lua. NPC, их диалоги, магазины, порталы, точки спавна монстров — всё описано скриптами по картам. Захотел нового NPC в Пайоне — открыл payon.lua и дописал.


За эталон взят rAthena

Если вы когда-то поднимали приватный сервер РО, то знаете rAthena — эмулятор официального сервера с открытым кодом. Вместе с предшественниками (Athena, eAthena) сообщество пилит его больше двадцати лет. В нём собраны формулы урона, шанс попадания, дроп, спавны монстров, скрипты всех NPC.

Я решил: механика должна быть как в pre-renewal (тот самый «классический» РО до глобального ребаланса). Поэтому rAthena — наш справочник. Урон ближнего боя, HIT/FLEE, крит и Perfect Dodge, ASPD, перегруз, потеря опыта при смерти, формула Max HP — всё сверено с исходниками rAthena. Даже ID предметов и монстров — те же, что в rAthena: Поринг — 1002, Яблоко — 512. Это сильно упрощает жизнь: можно взять их базу и импортировать.

Под это у нас есть свои скрипты: import_rathena_mob.py берёт монстра из базы rAthena и делает миграцию для нашей базы — со статами, опытом и всем дропом. Аналогично с предметами.


Как мы делаем карты

Это, пожалуй, самая интересная часть.

Карты в оригинальном РО хранятся внутри огромного архива data.grf (в нашем клиенте он весит 4,8 ГБ). Каждая карта — это несколько файлов в старых корейских форматах:

  • GND — земля: сетка тайлов с текстурами и освещением;

  • RSW — «сцена»: где стоят дома, деревья, источники звука, вода;

  • RSM — 3D-модели этих домов и деревьев;

  • GAT — сетка проходимости: где можно ходить, где стена, где вода.

Мы написали свой конвертер ro_map на Python. Он открывает GRF прямо через отображение файла в память (иначе 4,8 ГБ в оперативку не впихнёшь), достаёт карту, разбирает все эти форматы и собирает из неё glTF — стандартный 3D-формат, который Godot открывает как родной. Отдельно сохраняется сетка проходимости, мини-карта, экран загрузки и фоновые звуки (журчание фонтана, ветер, птицы — а они в РО, кстати, лежат в древнем Microsoft ADPCM, пришлось и его декодировать).

Пара забавных грабель:

  • Земля «квадратиками». У каждого тайла земли в РО свой цвет в каждом углу. В лоб перенесёшь — и вся трава становится шахматной доской из чуть разных оттенков. Пришлось склеивать соседние тайлы так, чтобы угол был общим, а цвет в нём — средним. Пересобрали все карты — земля стала мягкой, как в оригинале.

  • Модели нескольких версий. RSM бывают 1.4, 1.5, 2.2, 2.3… и у каждой свои сюрпризы. Например, конвертер падал на RSM 1.5, потому что ожидал там поля из 1.6.

  • Монстры за краем карты. На многих картах РО по самому краю идёт «проходимая» рамка, куда игроку не попасть. В пещере Пайона я видел монстров, стоящих на чёрных клетках за стенами. Оказалось, rAthena обходит это так: случайный спавн «по всей карте» не ставит монстра ближе 15 клеток к краю. Сделали так же.

А вот NPC, порталы и спавны берутся из скриптов rAthena. Для этого есть скрипт rathena_maps.py: он читает, где на карте стоят варпы и сколько каких монстров там живёт, и генерирует наши Lua-файлы. Например, на первом поле Пайона — 10 Willow, 10 Poporing, 10 Poring, 100 Spore и россыпь Black Mushroom по конкретным клеткам. Ровно как было.

А чтобы ничего не потерялось, тот же скрипт умеет сверять: проходит по всем варпам rAthena между нашими картами и показывает, где у нас переход пропущен или ведёт не туда. После такой проверки нашёлся, например, забытый домик у причала Альберты.

пирамида Морока, этаж с мумиями

пирамида Морока, этаж с мумиями

деревня орков на полях Гефена

деревня орков на полях Гефена

Гефен и его башня

Гефен и его башня


Карта мира

Отдельная гордость — карта мира. Помните окошко с континентом Рун-Мидгард по Ctrl+~? Оно у нас есть, и картинка та же, из клиента РО. Но разметку пришлось добывать с приключениями: в клиенте она лежит в Lua-скриптах, скомпилированных в байт-код Lua 5.1 для 32-битной программы. Скрипт world_map.py читает этот байт-код через библиотеку lupa, достаёт оттуда, где на карте какой город и какое поле, и склеивает с нашими данными.

И вот тут мы пошли дальше оригинала. В РО карта мира показывает только названия. У нас:

  • места, куда уже можно дойти, подсвечены, а те, что ещё не сделаны, затемнены;

  • подземелья отмечены метками, а твоё текущее место — жёлтым;

  • щёлкаешь по полю — справа появляется список: какие там монстры, какого уровня и сколько, какие NPC, есть ли Kafra и куда ведут проходы.

То есть это одновременно и карта, и маленькая энциклопедия: прежде чем идти фармить, можно посмотреть, кто там живёт. А тест на сервере следит, чтобы данные карты мира не отставали от реальных спавнов, NPC и переходов.

карта мира: выбрано поле Гефена 10 — орки, Orc Lord, Kafra и проходы

карта мира: выбрано поле Гефена 10 — орки, Orc Lord, Kafra и проходы


Как оживают монстры

Спрайты в РО — это пары файлов SPR (картинки) и ACT (анимации: какие кадры, в каком порядке, с какими смещениями). Второй наш конвертер, ro_sprite, превращает их в атласы для Godot. Персонаж собирается из слоёв: тело, голова, причёска, шапка, оружие в руке — как в оригинале.

Мир у нас настоящий 3D, а спрайты — плоские «картонки», всегда повёрнутые к камере. У каждой 8 направлений, и клиент сам решает, какой ракурс показать в зависимости от того, куда смотрит монстр и откуда смотрит камера.

Мелочь, которая очень важна для ощущения РО: выбор мышью попиксельный. Кликнуть по монстру можно только по его видимым пикселям, а не по прямоугольнику вокруг. Иначе в толпе Порингов начинается ад.

Поведение монстров живёт на сервере: их логика работает по таймерам, как в rAthena — агрессивные бросаются, пассивные бродят, кто-то подбирает вещи с земли. Если рядом нет ни одного игрока, монстр «засыпает» и думает в десять раз реже — это сильно экономит процессор. А на клиенте анимацию «стоит/идёт» крутят деревья поведения (плагин LimboAI для Godot).

Звуки у каждого монстра — свои, оригинальные: тот самый «плюх» Поринга никуда не делся.

Поринги на поле Пронтеры (для съёмки подсыпали погуще)

Мечник против стайки Порингов, Drops и Lunatic

Мечник против стайки Порингов, Drops и Lunatic


Выдержит ли Python?

Однажды я спросил: а сколько вообще выдержит сервер? Решили проверить честно — 100 игроков и 5000 монстров.

Написали нагрузочный тест: боты подключаются по тому же протоколу, что и настоящий клиент, бегают по картам, бьют монстров, подбирают дроп, пишут в чат и кидаются смайликами.

Первый результат был… отрезвляющим. Сервер должен «тикать» 60 раз в секунду, а один тик занимал почти секунду. Вход 100 игроков разом замораживал мир на 20 секунд — потому что проверка паролей (bcrypt) выполнялась прямо в игровом цикле.

Профилировщик показал, куда уходит время: сервер каждый тик рассылал позицию каждого идущего монстра каждому игроку на карте. Поправили так, как это сделано в самом РО:

  • сервер сообщает только куда монстр пошёл, а клиент сам ведёт его до точки;

  • каждый игрок видит только то, что в радиусе 40 клеток вокруг него (в rAthena по умолчанию 14), а искать соседей помогает пространственный индекс — мир поделён на «корзины», и смотрим только соседние;

  • пакет кодируется один раз, а не для каждого получателя;

  • пароли проверяются в отдельном потоке.

Итог: тик упал с 668 до 31 миллисекунды, трафик одного игрока среди 5000 монстров — с 5500 до 110 пакетов в секунду. До 2000 монстров и 100 игроков сервер держит честные 60 тиков в секунду на одном ядре. Для фанатского проекта — более чем.


Что получилось лучше, чем в оригинале

Мы стараемся быть «как в РО», но кое-где позволили себе улучшения.

Персонаж больше не ходит зигзагом. В РО (и у нас поначалу) поиск пути выдаёт «лесенку» из диагоналей и прямых. Мой отзыв из баг-трекера дословно: «Идёт… как алкоголик, шатаясь». Теперь путь сглаживается: если дорога свободна, персонаж идёт по прямой, а у стен аккуратно огибает углы.

Небо. В РО камера смотрит почти сверху, и неба там толком не видно. У нас над Пронтерой — шейдер неба: синий зенит, солнце с ореолом, медленно плывущие облака и дымка у горизонта, а за городскими стенами — поля и силуэты холмов.

небо над Пронтерой

небо над Пронтерой

поле Пронтеры, на горизонте замок

поле Пронтеры, на горизонте замок

Камера свободнее, чем в РО: можно опустить её почти к земле и увидеть горизонт — в оригинале наклон сильно ограничен.

Питомцы с аксессуарами, которых в РО не было. Drops и Poporing — это перекраски Поринга, но рюкзачок, как у Поринга, им в оригинале не нарисовали. Мы собрали спрайт сами: тело своё, рюкзак — от Поринга. Мелочь, а приятно.

Игра под все системы. Оригинальный клиент — только Windows. У нас одна команда собирает Windows, Linux, macOS и веб-версию.

Карта мира с «энциклопедией» — монстры, NPC, Kafra и проходы по щелчку (подробнее выше).

Вход через Google — помимо обычного логина и пароля.

И при этом мы честно сохраняем то, что делает РО — РО. Иногда даже баги: в Мороке стена вокруг дворца проходима между столбами. Проверили по данным оригинала — там она тоже проходима. Пока оставили, вынесли «на подумать».


А как это — разрабатывать с нейросетью?

Мой процесс выглядит так: я играю, нахожу проблему или хочу новую фичу — и пишу как есть, человеческим языком. «В Мороке я прошёл сквозь угол здания. Кроме того, монстры появляются за пределами локации». Дальше нейросеть сама лезет в код, в исходники rAthena, в данные клиента, делает изменение, пишет тесты и обновляет документацию.

Каждое изменение попадает в журнал версий, и в каждой записи есть раздел «Запрос пользователя» — с моей дословной цитатой. Можно открыть любую из 223 версий и увидеть, с какой фразы всё началось.

Чтобы это не превратилось в хаос, есть жёсткие правила:

  • тесты на всё: больше двух тысяч на сервере и больше тысячи на клиенте, а сервер обязан держать 100% покрытия;

  • проверка типов и линтер держатся на нуле ошибок;

  • документация обновляется вместе с кодом — иначе нейросеть в следующий раз просто не узнает, как всё устроено;

  • бэклог: если что-то заметили, но не чиним сейчас — оно записывается.

Самый ценный навык в таком режиме — не писать код, а точно формулировать, чего хочешь, и играть, играть, играть, проверяя результат.


Что дальше

Ближайшие планы:

  • Боссы (MVP) как в РО: сейчас Осирис, Амон Ра, Фрионни и Эддга уже стоят на своих картах, но пока ведут себя как обычные монстры. Хочется настоящих MVP — со свитой, телепортами и наградой.

  • Торговля: лавки Vending и аукцион.

  • Превращения монстров: Pupa, вылупляющаяся в Creamy, яйца Thief Bug.

  • Гильдии, друзья и вторые профессии — Рыцари, Визарды, Хантеры и вся компания.

  • Новые города и континенты: Альдебаран, Гласт Хейм, Мьёльнир — переходы на них уже прописаны, ждут своих карт.

  • Разделение сервера на процессы по картам — как map-server в rAthena. План уже написан; браться будем, когда игроков станет больше, чем держит одно ядро.

  • Создание автопатчера - чтобы не перекачивать игру каждый раз, когда выходят обновления.

  • Аренда сервера - чтобы пустить желающих поиграть. Хотя не думаю, что их будет много.


Вместо заключения

Через двадцать с лишним лет после того, как я впервые вышел за ворота Пронтеры, я снова там. Только теперь — внутри игры, которую делаю сам.

Если интересно — напишите в комментариях, про что рассказать подробнее: про конвертацию карт, про сетевой код, про то, как устроены экзамены на профессию, или про работу в паре с нейросетью. И, конечно, делитесь своими воспоминаниями о РО: на каком сервере играли, кем, какой был ник?

Поринги передают привет. Плюх.

у фонтана Пронтеры

у фонтана Пронтеры

Пара слов о правах: графика, карты и звуки — из оригинального клиента РО, все права на них у Gravity. Проект некоммерческий, фанатский, и денег я на нём зарабатывать не собираюсь.

Показать полностью 11
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества