Как поиграть в Quake для DOS по сети в 2023 году

в 9:00, , рубрики: docker, docker-compose, dosbox, IPX, ruvds_статьи, vps, Блог компании RUVDS.com, виртуализация, Игры и игровые консоли, Разработка под Linux, системное администрирование, эмуляция

Как поиграть в Quake для DOS по сети в 2023 году - 1


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

  • не на всех компьютерах можно поиграть со звуком;
  • необходимо заменять файл в дистрибутиве Quake;
  • невозможно поиграть по сети.

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

Исходный код решения вы можете найти в моём репозитории на GitHub. Использовать его можно по своему усмотрению. Загрузить и запустить или воспользоваться для прояснения моментов, которые могут оказаться сложными, — решать вам.

Когда я учился на первом и втором курсах института, игра Quake была хитом. Играли в неё в компьютерных клубах или дома, если кто-то был редким обладателем компьютера. Мы, студенты, всегда искали возможность поиграть в неё в компьютерном классе — уж очень привлекательны были сетевые возможности Quake для нас, людей, не избалованных современным интернетом. Даже те, у кого был компьютер дома, приходили в институт из-за возможности поиграть по локальной сети.

Локальная сеть была организована на основе протоколов IPX/SPX. Про TCP/IP можно было почитать в журналах или умных книжках, которые мы, к сожалению, тоже редко видели.
Сегодня вы можете вернуть себе и вашим друзьям те ощущения азарта от сетевой игры в Quake для DOS. Причём неважно, где находятся ваши друзья — главное, чтобы у них было стабильное и относительно быстрое интернет-соединение.

Для меня сам факт того, что ты играешь в ту самую игру, в которую играл более 25 лет назад, вызывает приятные приступы ностальгии. Надеюсь, я не одинок.

В 90-е в компьютерных классах моего института стояли компьютеры без звуковых карт, поэтому игра мне запомнилась без звука. Сейчас же, используя эмуляцию, можно будет поиграть со звуком.

Что понадобится

  1. Эмулятор DOSBox Staging.
  2. VPS с Linux. Например, с Ubuntu 20.04.
  3. Docker и утилита docker-compose.
  4. Файлы игры Quake для DOS, которые можно найти в интернете.

Немного теории

Для начала нам не повредит немного теории. Если читатель знаком с теорией или она ему не нужна, то можно сразу перейти к делу.

▍ Технологии виртуализации и эмуляции

Виртуализация и эмуляция сейчас используются практически везде. На это есть ряд причин:

  • экономятся ресурсы, так как на одном физическом компьютере могут работать несколько виртуальных компьютеров;
  • независимость от платформы, так как можно работать с программами для архитектур, физических реализаций которых у вас нет;
  • упрощается развёртывание приложений, так как вы без труда можете создать виртуальную машину, содержащую нужное вам программное и аппаратное обеспечение.

VPS, Docker и эмулятор DosBox Staging, используемые в статье, относятся к этим технологиям.

▍ Компьютерные сети

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

▍ NAT

С большой долей вероятности доступ в интернет вам предоставляется с помощью Network Address Translation (NAT), поэтому кратко рассмотрим эту технологию, не вдаваясь в скучные и утомительные подробности.

NAT позволяет нескольким компьютерам использовать один и тот же глобальный IP-адрес в интернете. Среднестатистический пользователь в большинстве случаев не заметит разницы, разделяет ли он IP-адрес в интернете с кем-то или нет. Исключением может быть ситуация, когда он увидит на каком-нибудь сайте сообщение, что его IP-адрес забанен из-за большого количества запросов, или когда у него возникнут сложности с загрузкой редкого торрента.

Но если вы захотите создать на своём компьютере сервер, а ваш провайдер предоставляет доступ с использованием NAT, то обратиться к серверу из интернета будет сложно или вообще невозможно. Поэтому часто для размещения своих серверов в интернете используют технологию Virtual Private Server (VPS).

▍ Virtual Private Server

Организации, которые предоставляют услугу VPS, называются хостинг-провайдерами. До того, как технологии виртуализации вошли в нашу жизнь, хостинг-провайдеры предоставляли менее удобные (Website Hosting) и более дорогие (Dedicated Server) услуги. Хотя и сейчас вы можете себе их заказать.

У хостинг-провайдера есть определённый пул физических компьютеров, а пользователями арендуются виртуальные машины (компьютеры), запускаемые на компьютерах из этого пула.
Эта услуга выгодна как провайдеру, так и конечному пользователю. Провайдер может более рационально использовать имеющийся у него пул физических компьютеров, а пользователь получает виртуальный компьютер, почти не отличающийся от реального, по гораздо меньшей цене, чем в случае аренды реального компьютера.

Благодаря современным графическим пользовательским интерфейсам провайдера, создание VPS осуществляется быстро и удобно, всего за несколько минут.

Пользователи получают полноценный узел в интернете, который могут использовать по своему усмотрению. Это может быть персональный сайт, VPN-сервер, игровой сервер. Применение ограничивается только фантазией, знаниями и умениями пользователя.

Многие задачи по администрированию VPS выполняются на стороне хостинг-провайдера. Пользователям не нужно заботиться о том, чтобы компьютер работал 24/7 — это задача провайдера. Инфраструктура провайдера адаптирована к различным непредвиденным случаям вроде отключения электричества или поломки жёсткого диска.

▍ Туннелирование в компьютерных сетях

Суть туннелирования заключается в том, что пакеты из одного протокола передачи данных помещаются без изменения в пакеты другого для передачи по сети. Говорят, что второй протокол является транспортным протоколом для другого. Чаще всего туннелирование, обычно совместно с шифрованием, используется для организации VPN (Virtual Private Network).

В нашем случае мы будем использовать UDP-туннель для передачи пакетов IPX. Иными словами, пакеты IPX будут упаковываться в пакеты UDP и передаваться в сети. Это сделает возможным использование протокола IPX в интернете.

▍ Firewall

Если вы размещаете сервер в интернете, то вам лучше защитить его при помощи Firewall. В Firewall прописываются правила, которые определяют на базовом уровне, откуда можно обратиться к вашему серверу и к каким службам сервера. К счастью, большинство провайдеров VPS позволяют очень просто настроить эти правила из графического интерфейса.

Используемые приложения

▍ DOSBox Staging

Ранее я практически не сталкивался с этим эмулятором. Если я хотел запустить приложения для DOS, то использовал виртуальные машины (VMWare Player, VMWare Workstation, Oracle Virtual Box) или эмуляторы (Bochs, Qemu). Попробовав DOSBox, а потом и DOSBox Staging, я понял для себя, что последний лучше всего подходит для запуска старых игр для DOS.

Изначально я недооценивал этот эмулятор, считая его просто упрощённой версией VMWare, Virtual Box или Qemu. Однако из-за того, что его назначение узкоспециализированное – эмуляция DOS, его скорость и точность эмуляции впечатляют.

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

▍ Ipxbox

IPX-сеть можно создать, используя команду ipxnet startserver в консоли DOSBox Staging, но это решение не очень удобное, если размещать сервер IPX на VPS. Поэтому, я думаю, лучше использовать внешний по отношению к DOSBox IPX-сервер. Варианты внешних серверов с сайта DOSBox, оказались слишком устаревшими, и мне не удалось быстро заставить их работать, поэтому я воспользовался ipxbox.

Ipxbox — это программа, написанная на языке Go, позволяющая организовывать IPX-сеть из экземпляров DOSBox в TCP/IP сети. Если интересно, что ещё позволяет делать программа, можете посмотреть дополнительную информацию на сайте или на YouTube-канале автора программы.

▍ Docker

Чем больше я использую Docker, тем больше убеждаюсь в том, что это универсальное решение, которому можно найти всё больше и больше применений. В нашем случае я создал Docker-образы dedicated-сервера Quake и программы ipxbox.

Вероятно, можно было найти уже современную реализацию сервера Quake для Linux и упаковать его в Docker-образ, но тогда нужно было бы думать, как настроить TCP/IP в DOS. Поэтому я решил создать докер-образ с Quake для DOS, а не Linux. Получилось интересное, на мой взгляд, и работающее решение – Quake для DOS, запускаемый в Docker-контейнере.

▍ Утилита docker-compose

Нам понадобится несколько Docker-контейнеров: один контейнер с IPX-сервером и один или несколько контейнеров с Quake-серверами. Управлять таким вроде бы и небольшим разнообразием уже не так удобно, как одним контейнером, поэтому нам поможет утилита docker-compose.

Docker-compose позволяет создавать несколько Docker-контейнеров и управлять ими. Структура мультиконтейнерного приложения описывается в файле docker-compose.yml.

Реализация

▍ Настройка Quake на локальном компьютере

  1. Загружаем Quake с сайта archive.org.
  2. Распаковываем содержимое архива в папку, например, C:Gamesquake.
  3. Меняем содержимое файла start.bat на QUAKE.EXE -nocdaudio.
  4. Загружаем DOSBox Staging.
  5. Устанавливаем, запускаем и закрываем DOSBox Staging. Устанавливать лучше только для своего пользователя.
  6. Модифицируем файл %USERPROFILE%AppDataLocalDOSBoxdosbox-staging.conf, чтобы удобнее было запускать в дальнейшем.

...
[ipx]
ipx = true

[autoexec]
mount c: c:games
c:
cd quake

Теперь в DOSBox Staging для запуска Quake можно будет просто ввести в консоли start.

▍ Организация сетевого варианта игры Quake

Если у вас есть локальная сеть, то перед запуском Quake можно на одном из компьютеров запустить IPX-сервер при помощи команды в DOSBox консоли:

DOSBOX> ipxnet startserver 10000

Где 10000 — это номер UDP-порта, на котором будет запущен IPX-сервер. Разумеется, вы можете использовать другой порт.

Остальные игроки в локальной сети могут подключиться к этой созданной IPX-сети с помощью команды:

DOSBOX> ipxnet connect your.machine 10000

Где your.machine — это IP-адрес или доменное имя компьютера, на котором запущен IPX-сервер.
Теперь вы можете играть по сети, только сеть локальная, а подключиться к ней из интернета будет проблематично. Я решил эту проблему путём создания общедоступного сервера IPX в сети Internet. Чтобы всех игроков поставить в равные условия, я также создал dedicated-сервер Quake, а вернее два, чтобы добавить универсальности решению.

▍ Настройка общедоступного сервера IPX и dedicated-сервера Quake

Самый простой способ запустить IPX-сервер и dedicated Quake сервера — загрузить созданный мной docker-compose.yml файл из интернета и выполнить в директории с файлом docker-compose.yml следующую команду:

$ docker-compose up -d

Чтобы остановить и удалить сервера, выполняются команды:

$ docker-compose stop
$ docker-compose rm

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

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

Для ясности структура директорий с файлами приведена на рисунке.

Как поиграть в Quake для DOS по сети в 2023 году - 2

Структура проекта

▍ 1. Создаём Docker-образ для IPX-сервера

FROM ubuntu:22.04 as builder
RUN apt-get update && apt install --yes golang libpcap-dev openssl ca-certificates

RUN mkdir -p /app/
WORKDIR /app/

RUN go mod init m.test
ARG CERT_LOCATION=/usr/local/share/ca-certificates
RUN mkdir -p ${CERT_LOCATION}
RUN openssl s_client -showcerts -connect github.com:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > ${CERT_LOCATION}/github.crt
RUN openssl s_client -showcerts -connect proxy.golang.org:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >  ${CERT_LOCATION}/proxy.golang.crt
RUN update-ca-certificates
RUN go get github.com/fragglet/ipxbox
RUN go build github.com/fragglet/ipxbox 

FROM ubuntu:22.04
RUN apt-get update 
RUN apt install --yes libpcap-dev
WORKDIR /app
COPY --from=builder /app/ipxbox /app/ipxbox
CMD ./ipxbox --port 10000

Файл ipxbox/Dockerfile

Чтобы созданный Docker-образ содержал меньше ненужных данных, в Dockerfile описываем так называемый multistage build. Он подразумевает, что в одном Dockerfile описывается один Docker-образ со средой для сборки, а второй для размещения собранных файлов. В результате Docker-образ будет занимать меньше места на диске.

▍ 2. Создаём Docker-образ для Quake-сервера

FROM ubuntu:20.04
RUN apt update && apt install --yes software-properties-common 
RUN add-apt-repository ppa:feignint/dosbox-staging && 
    apt update && 
    apt install --yes dosbox-staging gettext

RUN mkdir -p /app/quake
COPY quake/ /app/quake

ENV SDL_VIDEODRIVER=dummy
ENV IPX_SERVER_ADDRESS=192.168.0.161
ENV IPX_SERVER_PORT=10000
ENV QUAKE_SERVER_NAME="DEFAULT SERVER" 

COPY dosbox-staging.conf.templ /app/dosbox-staging.conf.templ
COPY quake-config.cfg.templ /app/quake-config.cfg.templ
COPY start.sh /app/start.sh
RUN chmod 777 /app/start.sh

CMD /app/start.sh

Файл quake-server/Dockerfile

При запуске Docker-контейнера у нас будут добавлены следующие переменные окружения: SDL_VIDEO_DRIVER, IPX_SERVER_ADDRESS, IPX_SERVER_PORТ и QUAKE_SERVER_NAME.

SDL_VIDEO_DRIVER нужно проинициализировать значением dummy, чтобы DOSBox запустился в так называемом headless mode, т. е. без использования графических возможностей. Для сервера они нам не нужны.

IPX_SERVER_ADDRESS и IPX_SERVER_PORT нужны, чтобы указать DOSBox, где находится IPX-сервер.

QUAKE_SERVER_NAME — это имя dedicated Quake-сервера, который будет отображаться в списке при подсоединении к сетевой игре.

Файлы dosbox-staging.conf.templ и quake-config.cfg.templ — это шаблоны конфигураций DOSBox и Quake, которые преобразовываются в файлы конфигурации при запуске скрипта start.sh.

Скрипт start.sh, помимо этого, ещё выполняет задержку в 10 секунд перед запуском dedicated Quake-сервера. Это нужно, чтобы IPX-сервер успел загрузиться до запуска dedicated Quake-сервера. Решение неэлегантное, но на первый случай сгодится ввиду своей простоты.

Для скрипта start.sh устанавливаются атрибуты 777, чтобы его можно было запустить. По умолчанию git не хранит атрибуты файлов — можно или повозиться с настройкой Git или воспользоваться этим решением.

▍ 3. Описываем структуру мультиконтейнерного Docker-приложения

version: "3.9"
services:
  ipxserver:
    restart: always
    build: ipxbox/.
    ports:
      - "10000:10000/udp"
    image: "artyomsoft/ipxbox"
  gameserver1:
    restart: always
    build: quake-server/.
    depends_on:
      - ipxserver
    environment:
      - IPX_SERVER_ADDRESS=ipxserver
      - IPX_SERVER_PORT=10000
      - QUAKE_SERVER_NAME=DEFAULT_S1
    image: "artyomsoft/quake-server"
  gameserver2:
    restart: always
    build: quake-server/.
    depends_on:
      - ipxserver
    environment:
      - IPX_SERVER_ADDRESS=ipxserver
      - IPX_SERVER_PORT=10000
      - QUAKE_SERVER_NAME=DEFAULT_S2
    image: "artyomsoft/quake-server"

Файл docker-compose.yml

Файл docker-compose.yml, думаю, понятен без дополнительных пояснений.

▍ 4. Выполняем запуск мультиконтейнерного приложения

$ docker-compose up --build --force-recreate -d

Опция build нужна, чтобы перед запуском контейнеров собрались образы для них, опция --force-recreate нужна, чтобы контейнеры пересоздавались при запуске, а опция d, чтобы они запускались в фоне.

▍ 5. Запускаем DOSBox c Quake и проверяем работу с нашим мультиконтейнерным приложением

DOSBOX> ipxnet connect 127.0.0.1 10000
DOSBOX> start

▍ 6. Выходим из DOSBox, останавливаем и удаляем Docker-контейнеры

$ docker-compose stop
$ docker-compose rm

▍ 7. Делаем релиз мультиконтейнерного приложения

Собираем и пушим образы на DockerHub:

$docker-compose build
$doker-compose push

Для хранения исходного приложения я использовал GitHub. Вы также можете создать публичный репозиторий на GitHub и поместить приложение туда.

Shell в Linux трепетно относится к окончаниям строк в файлах *.sh, поэтому убедитесь, что у вас файлы *.sh имеют Unix-окончание строк и явно пропишите это в файле .gitattributes.

Создайте репозиторий на GitHub, а потом у себя в корне проекта выполните следующие команды:

$ git init
$ git add .
$ git remote add origin <ссылка на ваш репозиторий>
$ git commit -m "Initial commit"
$ git push -u master origin

После успешного пуша репозитория на github создайте release и добавьте туда файл docker-compose.yml. Это позволит удобно скачивать этот файл по HTTP.

▍ 8. Выбираем VPS

Выбор VPS ограничивается вашими предпочтениями, финансовыми возможностями и требованиями созданного мультиконтейнерного Docker-приложения к ресурсам. В современных реалиях проблематично для жителей РФ арендовать VPS у иностранного хостинг-провайдера, поэтому нужно искать отечественный. Так как я хотел сделать всё быстро и просто, запустил своё приложение на тарифном плане Start от RUVDS. Проблем с производительностью я не заметил.

За стоимость двух поездок в метро или бургера вы получаете на месяц в пользование VPS, позволяющий вам играть в Quake для DOS по интернету с друзьями. Если вы сомневаетесь, можно заказать пробный период на 3-е суток (для новых пользователей) или воспользоваться другим хостинг-провайдером на ваш выбор.

Чтобы получить VPS, от вас требуется минимальная последовательность шагов:

  1. Регистрация аккаунта.
  2. Выбор тарифа для VPS и конфигурации сервера.
  3. Оплата.

Из всех параметров конфигурации сервера для тарифа Start, предложенных RUVDS, я поменял только операционную систему на Ubuntu 20.04 и через несколько минут я получил готовый VPS, к которому можно было присоединиться при помощи PuTTY или другого SSH-клиента.

Как поиграть в Quake для DOS по сети в 2023 году - 3

Конфигурация моего VPS

Если вы выберете расположение VPS за пределами РФ, стоимость его будет выше, но нам для Quake достаточно и на территории РФ.

RUVDS не является регистратором доменов, и если вы хотите, чтобы у вашего VPS было доменное имя, а не только IP-адрес, нужно у регистратора домена получить доменное имя и прописать адреса DNS RUVDS, а в личном кабинете на сайте RUVDS добавить полученное доменное имя к созданному VPS.

Как поиграть в Quake для DOS по сети в 2023 году - 4

Адреса DNS RUVDS

Как поиграть в Quake для DOS по сети в 2023 году - 5

Привязка доменного имени к VPS

▍ 9. Настраиваем Firewall

Для более безопасной работы VPS-сервера желательно настроить Firewall. Firewall настраиваем не в VPS, а на сайте хостинг-провайдера — это гораздо удобнее и требует от вас минимальных знаний.

  1. В вашем личном кабинете на сайте RUVDS выбираем созданный VPS.
  2. Заходим в настройки Firewall. Сеть -> Настроить фаервол для публичных адресов.
  3. Запрещаем все входящие соединения за исключением SSH и порта 10000 (на котором работает наш ipxbox). Для большей безопасности можно ещё разрешить доступ по SSH только с определённых IP адреса/адресов.
  4. Упорядочиваем правила как на рисунке ниже.
    Как поиграть в Quake для DOS по сети в 2023 году - 6

    Правила Firewall

  5. Нажимаем кнопку «Применить текущий набор правил».

▍ 10. Устанавливаем Docker и docker-compose на VPS

  1. Подключаемся к VPS по SSH.
  2. Вводим пользователя и пароль для VPS сервера.
  3. Вводим команды, приведённые ниже.

$apt update
$ apt install --yes docker.io curl
$ curl -SL https://github.com/docker/compose/releases/download/v2.15.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
$ ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
$ systemctl enable docker

Так как теперь Docker прописан в автозагрузку (команда systemclt enable docker), то и мультиконтейнерные приложения будет перезапускаться при перезагрузке VPS.

▍ 11. Загружаем и запускаем мультиконтейнерное приложение на VPS

$ cd ~
$ mkdir quake-servers 
$ cd quake-servers
$ curl -SL <http адрес вашего docker-compose.yml> -o docker-compose.yml
$ docker-compose up -d

Если вы создали свой GitHub-репозиторий и релиз в нём, то используйте http-ссылку на docker-compose.yml из него. Важно, чтобы VPS мог каким-то образом получить docker-compose.yml. А docker-compose мог загрузить и запустить Docker-образ.

▍ 12. Запускаем DOSBox Staging на локальном компьютере

DOS BOX> ipxnet connect <адрес вашего VPS> 10000 

DOS BOX> start 

▍ 13. Выбираем в Quake сетевую игру и протокол IPX, подключаемся к серверу Quake

Как поиграть в Quake для DOS по сети в 2023 году - 7

Выбор севера Quake

Как поиграть в Quake для DOS по сети в 2023 году - 8

Игровой процесс

Вы можете запустить два экземпляра DOSBox c Quake и таким образом проверить, как они работают по сети вместе.

Теперь вы можете делиться с друзьями адресом вашего ipxbox и играть с ними по сети в Quake для DOS, вспоминая те добрые времена. А ещё можно создать групповой звонок в Telegram, и тогда вы сможете делиться своими эмоциями голосом во время игры.

Заключение

Чтобы заставить всё работать как надо, я перепробовал несколько вариантов решения проблемы. Например, для создания IPX-сервера я изначально использовал эмулятор DOSBox, но потом посчитал, что использование выделенного сервера для IPX более элегантное решение.

Вместо Docker и docker-compose можно было обойтись systemd, но такое решение мне кажется более сложным и менее переносимым.

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

В частности, я знаю про следующие недостатки:

  1. При перезагрузке сервера IPX нужно отсоединиться и подсоединиться к IPX-сети в DOXBox Staging.
  2. Логирование из DosBox Staging некорректно работает в Docker-контейнере.
  3. Зная IP-адрес, пароль и порт сервера к нему может присоединиться любой пользователь.
  4. У серверов нет доменного имени, только IP-адрес.
  5. Не рассматривались вопросы масштабирования и отказоустойчивости.
  6. Docker-образы не оптимизировались по размеру.
  7. Quake-серверы просто ожидают несколько секунд запуска IPX-сервера, не проверяя, реально он загружен или нет. Поэтому теоретически при запуске Docker-контейнеров Quake-сервер может не найти IPX-сервер.
  8. Я не являюсь экспертом в настройке Quake. Я только настроил всё так, чтобы работало.

Несмотря на развлекательный характер статьи, вы получили базовые знания и умения по работе c VPS, узнали о технологиях виртуализации, базово научились пользоваться Firewall. Если у вас всё получилось, могу пожелать вам удачи в дальнейшем изучении Linux и сетевых технологий. Если нет, то попробуйте прочитать статью ещё раз, задать вопросы в комментариях или на форумах и сайтах на ваш выбор. Главное — правильно сформулировать вопрос, и у вас всё получится.

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

Автор:
artyomsoft

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js