# Плагины

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

## Как установить плагин

1. Первый способ. Через редактирование таблицы plugins\_list внутри plugins\_manager.lua
2. Такой же, как и первый, но можно там же не указывать поле data, а только order, а сам плагин с расширением .lua закинуть в папку plugins
3. Второй способ и самый удобный. Просто закинуть нужный плагин в папку plugins с расширением .lua, и он автоматически подхватится. Больше не нужно руками их добавлять в текстовом редакторе, просто переместить в папку. Если нужно настроить порядок вызова плагинов (вначале один, потом другой), то смотрите второй способ применения. Все варианты использования есть в плагин менеджере

## Список команд

* call\_function - вызвать какую-то функцию. Это может быть как серверная функция, так и зарегистрированная в общем пространстве функция другого плагина
* register\_function - зарегистрировать функцию, ее можно будет потом вызывать с помощью call\_function. Полезно, чтобы дать возможность другим плагинам получать какую-то инфу. Например, плагин system определяет функцию кика с соответствующим сообщением. И эту готовую функцию может использовать любой другой плагин
* register\_command - зарегистрировать команду. Например, мы хотим, чтобы при вводе команды /test игроку присылалось сообщение abrakadabra
* set\_data - установить данные (нужно для взаимодействия между плагинами)
* get\_data - получить данные (нужно для взаимодействия между плагинами). Например, нужно узнать ник игрока
* remove\_data - удалить данные
* send\_data - отправить данные. Можно отправлять данные клиенту. Правда, клиент будет реагировать только на те данные, список которых определен на его стороне. Например, можно с помощью этого плагина заставить игрока обновить данные карты
* set\_server\_state - установить состояние сервера (готов к взаимодействию, выключен, запускается)
* start - запустить сервер

### Какие события плагин отслеживает?

* init - запуск сервера
* verify\_registration - верификацию игрока (сервер проверяет, пускать ли игрока в игру или нет)
* on\_player\_registered - регистрацию игрока на сервере (когда игрок заходит, то ему выдается страна, он добавляется в список игроков)
* on\_player\_joined - момент, когда у игрока прогрузилась карта (например, отправлять ему просьбу отобразить правила раньше этого момента не имеет смысла, т.к. игрок в меню)
* on\_player\_disconnected - отключение игрока от сервера
* on\_data - данные, которые пришли от клиента
* before\_next - событие перед началом след. хода
* game\_over - завершение игры
* attribute\_message - оформление сообщения

## Разбор стандартного плагина afk

```
-- это нужно для работы модуля
local M = {}

-- подключаем модуль таймера
local timer_module = require "core.timer"

-- переменные для работы с функциями других плагинов или сервера: отправить данные, вызвать функцию, получить данные
local send_data
local call_function
local get_data

-- таблица с данными последней синхронизации с клиентами, хранят таймер и последнее время
local last_sync = {
    -- client = {
    --     timer_id,
    --     last_time
    -- }
}

-- ждем столько сек, если нет ответа, то кик
local afk_sec = 30

-- проверяем клиента
local function check_client(client)
    -- если текущее время минус время последней синхронизации больше 30 сек, то кикаем
    if socket.gettime() - last_sync[client].last_time > afk_sec then
        call_function("kick", client, { "", get_data("clients_data")[client].name, "lost connection"})
    end
    -- шлем сообщение клиенту, на которое он должен ответить
    local t = {
        type = "ping",
        data = {}
    }
    send_data(to_json(t), client)
end
-- вызывается один раз вначале. Тут мы определяем нужные нам функции
function M.init(api)
    send_data = api.send_data
    call_function = api.call_function
    get_data = api.get_data
end

-- вызывается в случае регистрации игрока
function M.on_player_registered(client)
    -- заполняем данные синхронизации нового клиента
    last_sync[client] = {
        -- создаем таймер, который каждые 30 сек проверяет наличие соединения
        timer_id = timer_module.every(afk_sec, function()
            check_client(client)
        end),
        last_time = socket.gettime()
    }
end

-- если клиент отключился, то удаляем данные
function M.on_player_disconnected(client)
    last_sync[client].timer_id:remove()
    last_sync[client] = nil
end

-- если игрок прислал ответ, то обновляем данные синхронизации
function M.on_data(data, ip, port, client)
    if data.type == "pong" then
        last_sync[client].last_time = socket.gettime()
    end
end

return M
```
