Mod OnlineCity for game RimWorld Author Vasilii Ivanov aka Aant
OnlineCity мод для игры RimWorld Автор Василий Иванов aka Aant
OnlineCity – это модуль сетевой игры для симулятора выживания RimWorld. Он позволяет нескольким игрокам играть на одной планете в режиме онлайн. После регистрации, вы сможете создать свое поселение и начать развиваться бок о бок с другими участниками. Вы сможете наблюдать за прогрессом соседей, их поселениями и караванами, но самое главное вы сможете оказывать друг другу вполне материальную помощь, передавая еду, медикаменты, оружие или любые другие вещи, включая поселенцев. Для этого необходимо лишь по всем правилам игры собрать караван и добраться до них!
Цель мода – сделать возможной игру с друзьями, не нарушая баланса и не снижая уровень погружения в игру. На данный момент жизненный путь мода только начался. Он обладает минимальным набором функций, чтобы предоставить вам возможность совместной игры. Вы можете видеть других игроков на карте планеты, переписываться с ними в чате и обмениваться товарами с караванами и поселениям. А разработка продолжается! За ее прогрессом вы можете следить в новостях группы.
Официальная страница мода: https://vk.com/rimworldonline (там же есть ссылки для финансовой помощи автору)
Общение в Дискорд: https://discord.gg/5DzWrnR
Почта emAnt@mail.ru
Процесс разработки на Trello: https://trello.com/b/gXtWtDjy/onlinecity-mod-rimworld
Текущий сервер для игры и тестов 194.87.95.90
Текущая версия RimWorld A18
Чтобы начать играть установите мод как обычно в папку Mods. Для работы также требуется установленный мод HugsLib. Таким образом минимальный набор может быть в такой последовательности: Core HugsLib OnlineCity
Мод должен быть совместим практически со всеми другими модами. Однако набор модов и, возможно, каких-то настроек может ограничиваться сервером, на котором вы хотите играть. Т.е. на одном сервере набор определенных (конфликтных) модов должен быть одинаков у всех игроков.
Синхронизация с сервером происходит каждые 5 секунд, полноценное сохранение – раз в 15 минут или при выходе из игры посредством меню. Не рекомендуется закрывать игру нажатием на крестик! Это может привести к потере прогресса игры с последнего сохранения.
Полезно знать:
-
Пока сетевая игра ориентирована только на взаимопомощь в выживании.
-
Цвет домов и караванов других игроков – синий. С ними можно взаимодействовать, выделив свой караван и нажав на них правой кнопкой мыши.
-
При передаче товаров учитывайте грузоподъемность караванов. При перегрузе караван не сможет передвигаться. Выделив караван, можно узнать сколько груза он ещё может принять.
-
Чтобы товары, полученные от сделок с другими игроками, складировались в определенном месте вашего поселения, переименуйте нужный склад так, чтобы он содержал символы "торг" или "trad".
-
В общем чате можно общаться со всеми игроками, которые находятся онлайн. Так же можно создать приватный канал для общения с одним игроком лично.
-
По щелчку любой кнопки мыши на никнейме игрока происходит добавление игрока в активный чат, открытие приватного канала чата, либо просмотр общей информации об игроке на выбор.
Разработка задумывается из папки OnlineCity в игровой папке Mods.
Проекты:
- Chat - утилита через которую можно залогиниться и общаться в общем чате
- Converter - утилита для перевода файла сохраненного мира на более новые версии
- RimWorldOnlineCity - библиотека мода прикрепляемая к игре
- ServerConsole - оболочка запуска сервера
- ServerDll - сервер, открывает указанный порт и радует игроков (по задумке)
- UnionDll - содержит модель и некоторый код, который используется и клиентом и сервером
Проект сервера ServerConsole разворачивается в специальную папку RimWorldOnlineCityServerOut Сама библиотека мода RimWorldOnlineCity в папку Assemblies так, что после компиляции можно сразу тестировать в игре.
Начать знакомство можно с:
- StartPoint.cs - здесь точка запуска нашего мода. Сейчас тут два класса которые добавляют кнопку на нижней панели в игре. И здесь же (в конструкторе) идет первая инициализация. Основная инициализация происходит после входа в игру (после логина или регистрации).
- SessionClientController.cs - тут собственно Init (который запускается из StartPoint), и InitConnected (начало работы над игрой сразу после коннекта и авторизации на сервере). А также тут функции с общими действиями.
- Dialog_MainOnlineCity.cs - основная форма игры, которая запускается по кнопке на нижней панели в игре. Сейчас, временно, при старте формы происходит запрос подключения к серверу и начало всех диалогов с пользователем.
Клиент.
- Начало обмена начинается на форме Dialog_LoginForm, либо Dialog_Registration.
- Они вызывают функции SessionClientController Login и Registration соответственно.
- Они вызывают создание подключения функцией SessionClientController.Connect.
- Она же вызывает Connect из класса SessionClient (он реализован как синглтон).
- Здесь происходит следующее (пока ключ на сессию передаётся открыто):
- Посылаем серверу первый пакет в один байт 0x00
- В ответ нам приходит симметричный ключ на сессию, которым мы будем шифровать и расшифровывать трафик
- Непосредственную связь обеспечивает ConnectClient и класс открывающий порт на сервере ConnectServer.
Весь дальнейший обмен происходит через функцию TransObject<>
- В TransObject<> запаковываем различные данные в стандартный единый контейнер ModelContainer и передаем серверу методом Trans.
- В Trans мы сериализуем объект в байты и сжимаем (GZip.ZipObjByte), шифруем (CryptoProvider.SymmetricEncrypt) и отправляем на сервер.
- Принитое сообщение от сервера расшифровываем, разжимаем и десериализуем в такой же стандартный единый контейнер ModelContainer. В нем, также, может быть передано сообщение об ошибке.
Сервер.
При установлении подключения возникает событие ServerManader.ConnectionAccepted в котором порождается отдельная нить и запускается обработчик DoClient, который порождает игровую сессию на сервере в виде класса SessionServer и запускает в нём метод Do.
В этом методе мы бесконечно слушаем поток и принимаем пакеты аналогично описанному у клиента выше, после чего полученный пакет "маршрутизируем" методом Service. Подробнее смотри ниже про сервер.
Клиент.
Для всех типов запросов создается своя функция в SessionClient.
В ней происходит запаковка передаваемых параметров в модель и запускается TransObject<> для передачи на сервер и приема ответа от него. В TransObject<> помимо данных передается также модель ожидаемого ответа и коды приема-передачи (обычно нечётное - запрос, а ответ это +1 от него).
Сервер.
- Принятый запрос в виде стандартного контейнера ModelContainer маршрутизируется функцией SessionServer.Service.
- Здесь на основе кода запроса выбирается обрабатывающая функция в классе Service. Можно сказать, что класс Service это аналог SessionClient для клиента (в том смысле, что в SessionClient мы вызываем функцию, а сервер обрабатывает в её зеркальном отражении в классе Service)
Для добавления нового обработчика на сервере соответственно добавляем функции в классы SessionClient и Service, и запись с новыми кодами внутри функции SessionServer.Service.