Показ дописів із міткою 7 Days to Die. Показати всі дописи
Показ дописів із міткою 7 Days to Die. Показати всі дописи

середа, 23 листопада 2016 р.

Добавляем поддержку HTTPS для микросервиса 7dtd.moon

При написании предыдущей заметки Программное формирования изображения на Go, мне понадобилось вставить пример формируемого изображения. Можно конечно это было сделать статическими картинками, но я решил использовать реальный пример работы. Так вот при это я столкнулся с проблемой что Blogger ругался на то что я вставляю картинки которые доступны по http а не по https на котором он работает по умолчании.
Сертификат будем использовать свободный, который выдает Let’s Encrypt, для получения самого сертификата воспользуемся утилитой СertBot. Данный процесс хорошо расписан на этих ресурсах и повторять его тут не имеет смысла.
И так приступим...
Первое это мы добавляем переменные которые будут указывать сам сертификат и закрытый ключ, и запускаем https сервер в отдельном потоке - гороутине (goroutine)
...
  log.Printf("Loading Certificates %s/%s/{privkey.pem,fullchain.pem}\n", *cert, *host)
  keyPath := filepath.Join(*cert, *host, "privkey.pem")
  certPath := filepath.Join(*cert, *host, "fullchain.pem")
...
/*** HTTPS ***/
  log.Println("Listening on https port: ", int(*port)+363)
  go func() {
    if err := http.ListenAndServeTLS(":"+strconv.Itoa(int(*port)+363), certPath, keyPath, nil); err != nil {
      log.Fatal("HTTPS Listen and Serve: ", err)
      os.Exit(1)
    }
  }()
...
Вот и все, теперь у нас есть два веб-сервера, один на порту 26980 (http) и второй на порту 27343 (https)

понеділок, 21 листопада 2016 р.

Удобный доступ к контейнеру Docker и другие вкусности :)

Сегодня пару коротких заметок о alias которые добавляют удобства для меня как администратора системы.

Первый alias
Так как я часто работаю с контейнерами Docker, и каждый раз для подключения к контейнеру писать docker attach мне лень, по этому я добавил себе в .profile
# Docker shell
alias dsh='function target(){ CONTAINER=$(docker inspect --format {{.State.Pid}} $1); sudo nsenter --target $CONTAINER --mount --uts --ipc --net --pid; }; target'
Теперь что бы получить "root" доступ к контейнеру, достаточно выполнить команду dsh

Второй alias
Вся суть этой команды, это показать актуальный лог файл игрового сервера. При перезапуске сервер формирует новый лог файл "logs/`date +%Y%m%d.%H%M%S`.log" и как обычно, лень как двигатель прогресса 😜 привела до написания этого alias, который как обычно добавил себе в .profile
# 7 Days to Die tools
alias tail7='grc -c conf.7dtd tail -f $(GAMELOG="/mnt/data/games/7DaysToDie/steam/games/7dtd/logs" && ls -tc ${GAMELOG} | echo "$GAMELOG/$(head -n1)")'
Дополнительная "плюшка" этого alias, это то что он еще раскрашивает лог файл.
Так как я иногда играя в игру, очень боюсь там собак, то я сделал себе такой вот "чит", перед тем как я подключаюсь к игре, я подключаюсь к серверу и запускаю эту команду и когда появляются собаки, консоль начинает "бибикать" 😎
Для раскраски лога, я использую утилиту Generic Colouriser, для которой я написал простенький конфигурационный файл conf.7dtd который нужно положить в ~/.grc/
# Spawned any zombies
regexp=.+Spawned.+|.+AIDirector.+
colours=yellow 
-
# Spawned Zombie Dog
regexp=.+Spawned.+Dog.+
colours=red beep
-
# Player info
regexp=.+Player.+
colours=green
-
regexp=.+ERR.+|.+EXC.+
colours=red
-
regexp=.+WRN.+|Warning.+|.+UNET.+
colours=magenta
-
regexp=(\d{4}\-\d{2}\-\d{2}).(\d{2}:\d{2}:\d{2})
colours=black, blue, blue bold
count=once
-
# Time: 6.00m FPS: 37.77 Heap: 250.0MB Max: 250.0MB
regexp=Time\: (\d{1,4}\.\d\dm) FPS\: (\d{1,3}\.\d\d) Heap\: (\d{1,4}\.\dMB) Max\: (\d{1,4}\.\dMB)
colours=default bold, blue bold, yellow bold, green bold, red bold
count=once
-
regexp=Ply\: (\d{1,2}) Zom\: (\d{1,2}) Ent\: (\d{1,2}) \((\d{1,2})\) Items\: (\d{1,2})
colours=default bold, green bold, red bold, yellow bold, yellow bold, blue bold
count=once
Вот так теперь радужно выглядит лог 😐

Программное формирования изображения на Go

Понадобилось мне при разработке мода на 7 Days to Die программно формировать изображение круга в зависимости от количества дней в игре. Так как я давно порывался посмотреть на Go, решил я использовать его для данной задачи. Да и подходит он для такого микро-сервиса в самый раз.
Сделать веб сервер на Go просто :) для этого используем стандартную библиотеку "net/http"
func main() {
  flag.Parse()
  log.Println("Starting tiny webserver for 7DTD moon texture...")
  log.Println("Document root path: ", *root)
  http.HandleFunc("/moon", moonHandler)
  log.Println("Listening on port: ", *port)
  if err := http.ListenAndServe(":"+strconv.Itoa(*port), nil); err != nil {
    log.Fatal("ERROR Listen and Serve: ", err)
  }
}
Дальше, формируем изображение круга с использование библиотеки "image/draw",
func moonHandler(w http.ResponseWriter, r *http.Request) {
  d := getDay(r)
  /*** Create colored image ***/
  dst := image.NewRGBA(image.Rect(0, 0, cXY.X+cR+1, cXY.Y+cR+1))
  draw.Draw(dst, dst.Bounds(), &circle{cXY, cR}, image.ZP, draw.Src)
  writeImg(w, dst)
}
и отдаем ее как картинку "image/png"
func writeImg(w http.ResponseWriter, img image.Image) {
  buffer := new(bytes.Buffer)
  if err := png.Encode(buffer, img); err != nil {
    log.Println("Unable to encode image: ", err)
    http.Error(w, err.Error(), http.StatusNotFound)
    return
  }

  w.Header().Set("Content-Type", "image/png")
  w.Header().Set("Content-Length", strconv.Itoa(len(buffer.Bytes())))

  if _, err := w.Write(buffer.Bytes()); err != nil {
    log.Println("Unable to write image: ", err)
    http.Error(w, err.Error(), http.StatusNotFound)
    return
  }
}
А теперь самое интересное, как же сделать эту картинку :)
Для этого описываем структуру:
type circle struct {
  P image.Point
  R int
}
И определяем методы которые описываю данную структуру в разрезе "image.Image"
func (c *circle) ColorModel() color.Model {
  return color.AlphaModel
}
func (c *circle) Bounds() image.Rectangle {
  return image.Rect(c.P.X-c.R, c.P.Y-c.R, c.P.X+c.R, c.P.Y+c.R)
}
func (c *circle) At(x, y int) color.Color {
  xx, yy, rr := float64(x-c.P.X), float64(y-c.P.Y), float64(c.R)
  if xx*xx+yy*yy < rr*rr {
    return color.Alpha{255}
  }
  return color.Alpha{0}
}
Все это прекрасно работает, но мне нужно было получить картинку с определенной прозрачностью, по этому пришлось немного изменить код функции "At" и структуры "circle". Добавляем поля для цвета и типа изображения (сплошная заливка или градиентная)
type circle struct {
  P image.Point
  R int
  C color.NRGBA
  S bool
}
... и теперь сама процедура отрисовки круга:
func (c *circle) At(x, y int) color.Color {
  xx, yy, rr := float64(x-c.P.X), float64(y-c.P.Y), float64(c.R)
  if xx*xx+yy*yy < rr*rr {
    xr := math.Abs(float64(c.P.X - x))
    yr := math.Abs(float64(c.P.Y - y))
    ar := uint8((1 - math.Sqrt(xr*xr+yr*yr)/float64(c.R)) * float64(c.C.A))
    if c.S {
      ar = c.C.A
    }
    return color.NRGBA{c.C.R, c.C.G, c.C.B, ar}
  }
  return color.Alpha{0}
}
В итоге, мы можем получить два вида кружкок :) задав параметры при обращении к веб серверу.
Градиентная заливка для 7 дня Сплошная заливка для 7 дня Градиентная заливка для 5-6 дня Сплошная заливка для 5-6 дня


Конечный результат как это все выглядит в игре :)

середа, 22 липня 2015 р.

Создаем игровой сервере 7 Days to Die. Немножко автоматизации.


И снова добрый день/вечер/ночь и тд. всем кто читает данный блог.
Потихоньку я осваиваю основы Docker и вникаю в его возможности и функционал. Тяжелый это труд все это описывать, проще все сделать быстренько за какой то часик, а потом тратишь несколько дней на оформление этого все в читабельный вид, что бы можно это все опубликовать. Ну что же продолжим... это было небольшое лирическое отступление :) что бы выровнять первый абзац с картинкой :)
Продолжаем наши эксперименты с Docker. Сегодня поупражняемся с созданием Dockerfile. Подопытным "кроликом" будет у нас все тот же 7 Days to Die.
Несколько слов о новых образах, которые теперь доступны через на официальном "Hub Docker".
~> docker search sovicua
NAME             DESCRIPTION           STARS     OFFICIAL   AUTOMATED
sovicua/debian   Debian Jessie (8.0)   0
Все они построены на базе Debian Jessie. На текущий момент есть два образа с тегами "jessie" и "steamcmd". Собственно первый это чистый Debian с установленными дополнительными пакетами и настроенной временной зоной. Данные настройки были описаны в Установка timezone в базовом образе Docker. Второй собран на базе первого с установленными библиотеками и steamcmd.
Итак, создаем файл конфигурации для создания образа контейнера.
~> mkdir docker/steamcmd/
~> cd docker/steamcmd/
~/d/steamcmd> vim Dockerfile
FROM sovicua/debian:jessie
MAINTAINER Viktor M. Sytnyk <sovicua sovic.org.ua>
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get install -y wget \
 && echo 'deb http://download.opensuse.org/repositories/shells:/fish:/release:/2/Debian_8.0/ /' >> /etc/apt/sources.list.d/fish.list \
 && wget http://download.opensuse.org/repositories/shells:fish:release:2/Debian_8.0/Release.key \
 && apt-key add - < Release.key \
 && apt-get update && apt-get upgrade -y \
 && apt-get install -y lib32gcc1 lib32stdc++6 fish && apt-get clean \
 && useradd -m -c "SteamCMD User" -s /usr/bin/fish steam
WORKDIR /home/steam/steamcmd
RUN wget http://media.steampowered.com/installer/steamcmd_linux.tar.gz \
 && tar -xvzf steamcmd_linux.tar.gz && rm steamcmd_linux.tar.gz \
 && chown -R steam:steam /home/steam
CMD /usr/bin/fish
Как вы можете видеть, shell по умолчанию я использую Fish Shell, хотя это не существенно, но понравился он мне :)
Создаем образ:
~/d/steamcmd> docker build -t sovicua/debian:steamcmd .
После этого можно выгрузить образ на Docker Hub:
~/d/steamcmd> docker push sovicua/debian:steamcmd
Теперь у нас есть готовый образ с установленным steamcmd, что позволит нам в дальнейшем быстро развернуть любую игру которая поддерживает установку с использованием данной утилиты. Теперь переходим к созданию образа с установленным сервером 7 Days to Die.
Для начала создадим файл скрипта с помощью которого будем устанавливать, а также обновлять саму игру.
~> mkdir docker/games/7dtd
~> cd docker/games/7dtd
~/d/steamcmd> vim 7dtd.steamcmd

login steam_user steam_password
force_install_dir /home/steam/games/7dtd
app_update 294420 validate
quit
Где, steam_user и steam_password это имя пользователя и пароль на учетной записи которого куплена эта игра.
Теперь создадим собственно сам файл конфигурации создания образа.
~/d/steamcmd> vim Dockerfile
FROM sovicua/debian:steamcmd
MAINTAINER Viktor M. Sytnyk <sovicua@sovic.org.ua>
WORKDIR /home/steam/steamcmd
COPY 7dtd.steamcmd /home/steam/steamcmd/
CMD /usr/bin/fish
Честно говоря, можно было бы и не делать данный образ, для этих целей можно бы использовать предыдущий образ, создав в нем скрипт установки и обновления игры, но раз уж автоматизируем то делаем все типа ка надо :) Изначально я планировал что бы при создании образа, сразу инсталлирована игра, но так как у меня настроен Steam Guard, то он запрашивал у меня код, так как это типа новая машина которая хочет получить доступ к моей учетной записи.
В Dockerfile была команда на запуск скрипта:
RUN ./steamcmd.sh +runscript 7dtd.steamcmd
Победить это, что бы инсталляция останавливалась при запросе кода, у меня так и не получилось. :( По этому инсталляцию придется выполнять руками уже в контейнере.
После этого создаем сам образ как обычно.
~/d/g/7dtd> docker build -t sovicua/games:7dtd
Вот что у нас получилось после всех этих процедур:
~/d/7dtd> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
sovicua/games   7dtd                c1c3539bbe2b        4 hours ago         594 MB
sovicua/debian  steamcmd            72ebdb1d894c        4 hours ago         594 MB
sovicua/debian  jessie              8ca03adc0398        27 hours ago        478.9 MB
Теперь мы можем быстренько создать контейнер:
~/d/7dtd> docker run --name="7dtd" --net="host" --user="steam" -i -t sovicua/games:7dtd
Выполняем инсталляцию игры, не забываем указать имя пользователя и пароль, если это не сделали раньше.
~/steamcmd> ./steamcmd.sh +runscript 7dtd.steamcmd
После инсталляции правим файл конфигурации сервера serverconfig.xml как вам удобно, и можно запускать сервер.
~/steamcmd> cd ../games/7dtd
~/g/7dtd> vim serverconfig.xml
Из параметров которые я у себя изменил, это установил пароль на доступ по telnet, и небольшие настройки самого сервера, такие как тройной лут и длина суток 2 часа реального времени. И еще пару параметров.
<property name="ServerName"             value="iHome Games Server" />
<property name="ServerPassword"         value="" />
<property name="ServerMaxPlayerCount"   value="4" />
<property name="ServerDescription"      value="iHome 7 Days to Die server" />
<property name="ServerWebsiteURL"       value="home.sovic.org.ua" />
...
<property name="DayNightLength"         value="120" />
<property name="DayLightLength"         value="18" />
...
<property name="DropOnDeath"            value="2" />
<property name="DropOnQuit"             value="0" />
...
<property name="CraftTimer"             value="0" />
<property name="LootTimer"              value="0" />
...
<property name="EnemySpawnMode"         value="4" />
...
<property name="LootAbundance"          value="300" />
<property name="LootRespawnDays"        value="30" />
Дополнительно, можно установить мод на сервер, который добавит пару дополнительных команд и самое вкусное что мне нравиться это возможность просмотра карты через веб. Очень помогает в поиске пещерок :) так как они редко сейчас встречаются, а на игровой карте искать не удобно, пока ищешь могут и "ушатать" :)
~/g/7dtd> wget http://illy.bz/fi/7dtd/server_fixes.tar.gz
~/g/7dtd> tar -xzvf server_fixes.tar.gz
Пример работы данного мода можно посмотреть у меня на сервере iHome 7 Days to Die server.
Ну вот и все, запускаем сервер:
~/g/7dtd> ./startserver.sh -configfile=serverconfig.xml
Если кто забыл, то напоминаю, что бы выйти с контейнера без его остановки, используем комбинацию клавиш Ctrl+p Ctrl+q.
На этом все, приятной игры. Если кто захочет поиграть вместе у меня на сервера, пишите.
Заходите на мой блог - UNIX и не только...

середа, 22 квітня 2015 р.

Игровой сервер 7 Days to Die

Ну вот я и дома, рабочий день закончился...
Иногда, когда просто все реально надоед и хочется просто отключить мозг и не думать о том что творится в стране, на работе и тд., я играю в разные игры жанра зомби-апокалипсис или песочницы, такие как DayZ, H1Z1, RUST, 7 Days to Die или в Minecraft :) куда же без него :)
Все эти игры жанра Online MMO Game, что совсем не очень то располагает к расслаблению, так как обычно там куча каких то неадекватных людей играет :( и ты быстрее умрешь от руки другого игрока чем от какого то зомби (Minecraft не считаем, так как там есть одиночный режим). Последнее время я выбираю 7 Days to Die, но самому играть не интересно, вначале конечно интересно бегать что то исследовать, но как обычно это заканчивается тем что тебя зомби быстро убивают. И приходится все начинать сначала.
Что бы хоть как то разнообразить это дело, и можно было поиграть в многопользовательский режим без всяких "бубуинов" с домашними или друзьями, я как обычно решил поднять на своем домашнем NASе, выделенный сервер для игры 7 Days to Die.  Но что бы не забивать основную ОС разными там библиотеками и тд. для этого я решил приспособить контейнеры Docker. Я не стал делать отдельный Dockerfile, так как это все делается для себя.

Итак, у меня уже был базовый образ для Debian Jessie, то его и будем использовать для создания игрового сервера.
Так как мне не нужно что бы контейнеру был выделенный отдельный сетевой адрес из подсети Docker, я использовал опцию --net=host, что позволило мне обращаться к контейнеру по адресу самого сервера.

Создаем новый контейнер
# docker run --net=host --name jessie -i -t sovicua:jessie
Обновляем образ
# apt-get update
# apt-get upgrade
Подготавливаем образ для установки SteamCMD, устанавливаем дополнительные библиотеки и утилиты
# apt-get install lib32gcc1 lib32stdc++6 wget
# useradd -m -c "SteamCMD User" -s /bin/bash steam
Скачиваем и устанавливаем SteamCMD
# su - steam
$ mkdir SteamCMD
$ cd SteamCMD/
$ wget http://media.steampowered.com/installer/steamcmd_linux.tar.gz
$ tar -xvzf steamcmd_linux.tar.gz
После установки, файл с архивом инсталляции можно удалить что бы не путался под ногами.
Запускаем steamcmd и устанавливаем игру в ~/games/7dtd/, app_id = 294420 для 7 Days to Die Linux Dedicated Server
Важное замечание:
Для игры 7 Days to Die, нужно регистрироваться под учетной записью где она у вас куплена, в остальных случаях можно регистрироваться под анонимным пользователем. Перечень доступных серверов которые можно создать с помощью SteamCMD и их параметры можно найти по ссылке Dedicated Servers List  
$ ./steamcmd.sh
... идет установка ...
Steam> login steam_user steam_password
Steam> force_install_dir ./../games/7dtd/
Steam> app_update 294420 validate
... идет установка ...
Success! App '294420' fully installed.
Steam> exit
Осталось немножко подправить файл конфигурации serverconfig.xml на свое усмотрение и можно запускать сервер.
Данный файл хорошо документирован, так что разобраться что и как нужно править думаю не составит большого труда.
Так же стоит исправить файл запуска сервера 7DaysToDie.sh, добавив опцию -configfile=serverconfig.xml и убрав добавление даты и времени к лог файлу. Кстати я так и не понял почему в данном файле закоментировано проверка платформы и запуск 64-битной версии, у меня что та 32 что 64 битная версия заработала.
$ cd ../games/7dtd/
$ cat 7DaysToDie.sh
#!/bin/sh

export LD_LIBRARY_PATH=~/.local/share/Steam/ubuntu12_32/steam-runtime/i386/usr/lib/i386-linux-gnu
#export MALLOC_CHECK_=0

#if [ $(getconf LONG_BIT) = 64 ]; then
#   ./7DaysToDie.x86_64 -configfile=serverconfig.xml -logfile 7DaysToDie_Data/output_log__`date +%Y-%m-%d__%H-%M-%S`.txt $@
#else
    ./7DaysToDie.x86 -configfile=serverconfig.xml -logfile 7DaysToDie_Data/output.log $@ &
#fi
Можно выполнить первый запуск.
$ ./7DaysToDie.sh
После первого запуска нужно подправить serveradmin.xml что бы назначить себя администратором. Обычно он лежит в ~/7 Days To Die/Saves/

После всех исправлений, запускаем еще раз сервер руками и проверяем что все работает и клиент подключается.
Для управления сервером, подключаемся к нему телнетом на порт 8081 (по умолчанию). Если все нормально, то останавливаем сервер командой shutdown через консоль управления.

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

Выходим из контейнера
$ exit
# exit
Сохраняем образ в локальном репозитории
# docker commit --author="Viktor M. Sytnyk <sovicua@mail.ua>" jessie sovicua/steam:7dtd
Можно посмотреть на созданный образ :)
# docker images

REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
sovicua/steam       7dtd                620bfd31cc61        About a minute ago   2.643 GB
sovicua             jessie              0d4a8604eed7        24 hours ago         423 MB
sovicua/games       minecraft           e2555d48e61b        10 weeks ago         835.3 MB
debian              jessie              58052b122b60        3 months ago         122.8 MB
Контейнер с которым мы до этого игрались, можно удалить, зачем он будет только место занимать.
Итак создаем контейнер с уже настроенной игрой, используя подготовленный образ и запускаем.
# docker run --net=host --name=7dtd --user=steam -t -i sovicua/steam:7dtd
$ cd ~/games/7dtd/
$ ./7DaysToDie.sh
Для выхода из контейнера используем комбинацию Ctrl+p Ctrl+q
В дальнейшем мы сможем подключиться к контейнеру используя команду
# docker attach 7dtd

В следующий раз мы попробуем создать игровой сервер для игры Factorio, для запуска которой требуется Х-сервер.