Wiki Kontra
Работа с плагинами
Обновлено: 23.04.2026 18:53

Работа с плагинами

🕒 Последнее изменение: 23 апреля 2026 в 18:53

Полное руководство по Plugin API и серверным Lua-скриптам KONTRA FPS

Данная страница содержит исчерпывающее руководство по работе с Plugin API для KONTRA FPS. Документация базируется на официальном API движка (C# → Lua wrapper) и подтверждённых на практике архитектурных паттернах. Этот документ обязателен к ознакомлению для разработчиков серверных систем.

📁 Прикреплённые файлы (Справочники API):
  • info properties or namespaces.txt — Базовый список пространств имён, объектов и энумераторов.
  • PROPERTIES.txt — Полный дамп свойств (Properties) и методов (Methods) серверного API движка.

1. Архитектура движка и основные объекты

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

  • Server — ядро сервера. Управляет сессиями (playerSessions), общим состоянием комнаты, конфигурацией и встроенной базой данных SQLite.
  • ServerSendNetLib — сетевая библиотека для отправки RPC клиентам (HUD, звуки, визуальные эффекты, изменение физики).
  • RconCommands — обработчик всех серверных команд (выдача оружия, смена команд, кик/бан, изменение настроек на лету).
  • GameManager.get_Instance() — менеджер игрового процесса. Отвечает за спавн энтити, подсчёт живых игроков, зоны покупки и завершение раундов.
  • Constants — системные константы и теги (например, теги поверхностей, лимиты, пути к папкам).

2. Игроки: Сессии (Player) vs Сущности (NetworkEntityPlayer)

Главное правило движка: необходимо чётко различать аккаунт игрока и его физическое воплощение на карте.

peer.Player (Сессия / Аккаунт)

Хранит метаданные, которые существуют, даже если игрок мёртв или находится в спектраторах.

lua
local player = peer.Player
local id = player.Id                    -- Уникальный ID сессии (до реконнекта)
local deviceId = player.deviceId        -- Hardware ID (для банов)
local money = player.Money              -- Баланс денег
local isAdmin = player.IsAdmin          -- Флаг администратора
local isVIP = player.IsVIP              -- Флаг VIP

peer.Player.NetworkEntityPlayer (Энтити / Персонаж)

Существует только когда игрок заспавнен. Если игрок мёртв или в спектраторах, методы могут выдавать ошибку или объект может отсутствовать.

lua
local ne = peer.Player.NetworkEntityPlayer
local hp = ne.Hp                        -- Здоровье
local isDead = ne.Dead                  -- Мёртв ли персонаж
local isT = ne.Terrorist                -- true = T, false = CT
local pos = ne.transform.position       -- Vector3 позиции на карте

ne:ButtonState(0) -- Проверка нажатия кнопок ne:SetHP(100, 0, -1, 0, 0) -- Выдача HP

Паттерн безопасного поиска игрока:

lua
for i = 1, 16 do
    local peer = Server.playerSessions[i]
    if peer and peer.Player then
        local ne = peer.Player.NetworkEntityPlayer
        if ne and not ne.Dead then
            -- Работа с живым персонажем
        end
    end
end

3. Жизненный цикл сервера и события

Скрипт должен подписываться на глобальные события, объявляя функции в таблице Server.

Ключевые события:

lua
function Server:Start()                       -- Инициализация скрипта
function Server:Stop()                        -- Выгрузка скрипта
function Server:RoomStateChanged(roomState)   -- Смена стадии матча
function Server:OnPlayerJoined(player)        -- Игрок успешно подключился
function Server:OnPlayerDisconnected(peer)    -- Игрок вышел (или вылетел)
function Server:OnPlayerDied(player)          -- Смерть игрока
function Server:OnRconCommand(peer, command)  -- Игрок ввёл команду в консоль
function Server:OnChatMessage(peer, message)  -- Сообщение в чат

Состояния комнаты (Util.RoomState):

  • 0waitingForPlayers (ожидание)
  • 1warmUp (разминка)
  • 6matchActive (Основное состояние для выполнения геймплейной логики)
  • 8matchEnd (конец раунда/матча)
  • 10mapVoting (голосование за карту)

4. Интерфейс (HUD) и Система меню

Вся отрисовка UI работает через ServerSendNetLib.EventMessage с использованием HTML-тегов форматирования.

Отрисовка текста на экране:

lua
ServerSendNetLib.EventMessage(
    peer, 
    "",                 -- Иконка
    "<b>Текст</b>",    -- HTML-содержимое
    3,                  -- eventType (3=flicker/menu)
    Color32(255,0,0,255), -- Цвет заголовка
    Color32(0,0,0,150),   -- Цвет фона
    "",                 -- Звук появления
    5000,               -- HUD ID
    15.0,               -- Время отображения
    600, -100,          -- Смещение X, Y
    100, 50,            -- Размеры W, H
    2,                  -- Выравнивание
    33                  -- Размер шрифта
)

Резервация HUD ID:

Никогда не перекрывайте ID, используемые ядром и другими скриптами:

  • 468 — Admin Menu
  • 110–113 — Invite HUD (многострочный)
  • 7810, 7820 — Системные меню (Дуэли, Телепорты)

Глобальный роутер ввода (Input Lock)

Если меню требует ввода цифр в чат (1, 2, 3), необходимо предотвратить конфликты между скриптами. Используйте паттерн Global Router:

  • При открытии меню скрипт захватывает lock на игрока: Router:Acquire(pid, "MY_SCRIPT").
  • Все нажатия в чат проверяются: if Router:IsOwner(pid, "MY_SCRIPT") then ... end.
  • При закрытии меню lock снимается.

5. Корутины, Тайминги и Задержки

В Lua скриптах KONTRA корутины являются стандартом для создания задержек, кулдаунов и периодических проверок.

lua
local isRunning = true
function Server:Stop() isRunning = false end

Coroutine(function()
    while true do
        if not isRunning then return true end

        -- Выполнение логики...
        
        return 0.1 -- Повторить через 0.1 сек
    end
end)

Важное правило Snapshot'ов: Если корутина использует переменные из внешнего скоупа (closure) и имеет задержку, сохраняйте локальные копии (snapshots) переменных до начала задержки, так как глобальный стейт может измениться.


6. Физика, Движение и Телепортация

Телепортация

Изменение transform.position должно происходить строго через pcall и с задержкой, если оно следует сразу за спавном или сменой команды.

lua
Coroutine(function()
    local wait = false
    if not wait then wait = true return 0.5 end
pcall(function()
    ne.transform.position = Vector3(x, y, z)
end)
return true

end)

Манипуляция скоростью (Velocity)

Движок позволяет применять импульсы прямо к клиенту через NetLib:

lua
ServerSendNetLib.AdditiveVelocity(peer, ne.LatestTick, Vector3Int(0, 500, 0))
ServerSendNetLib.OverrideVelocity(peer, ne.LatestTick, Vector3Int(0, 0, 0))

7. Встроенная база данных SQLite

В API встроена нативная поддержка SQLite для сохранения статистики, банов, инвентаря и т.д.

lua
local dbId = "MyModDB"
local dbPath = Constants.DATA_PATH .. "mymod.sqlite"

pcall(function()
    Server.CreateSQLConnection(dbId, dbPath)
    Server.ExecuteSQL(dbId, "CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, score INT)", nil)
end)

local args = {"12345678", 150}
Server.ExecuteSQL(dbId, "INSERT OR REPLACE INTO users (id, score) VALUES (?, ?)", args)

local result = Server.QuerySQL(dbId, "SELECT score FROM users WHERE id = ?", {"12345678"})

8. RCON Команды и Управление Геймплеем

Скрипты могут использовать движковые RCON команды для прямого воздействия на игроков:

  • ReviveCmd(nil, pid) — Воскресить игрока.
  • KillCmd(nil, pid) — Убить игрока.
  • SetTeamCmd(nil, pid .. " 0") — Перевести в T (0 = T, 1 = CT).
  • GiveCmd(nil, pid .. " " .. weaponId) — Выдать оружие/предмет по PrefabId.
  • EventCmd(nil, '"ЗАГОЛОВОК" "Сообщение"') — Вывести уведомление на экран.

9. Кастомные звуки и эффекты

Регистрация (Обязательно в Server:Start)

lua
pcall(function()
    Server.RegisterCustomSound({"mysound.mp3", "level_up.mp3"})
end)

Воспроизведение

lua
ServerSendNetLib.PlaySound(peer, "mysound.mp3")
ServerSendNetLib.PlaySound("level_up.mp3")
ServerSendNetLib.EffectRpc(Vector3(x,y,z), vfxId, soundId)

10. Золотые правила и частые ошибки (Best Practices)

⛔ ЧАСТЫЕ ОШИБКИ И КРАШИ:
  • Вызов функций до их объявления (Forward Declaration): В Lua локальная функция видна только ниже по коду. Если Функция А вызывает Функцию Б, сначала объявите local FuncB, а тело задайте позже.
  • Использование ipairs: ipairs прерывает цикл на первом nil. Массив Server.playerSessions может иметь "дыры". Всегда используйте for i = 1, 16 do.
  • Отсутствие pcall при работе с Transform: Энтити игрока может быть удалена в любой кадр (выход, смерть). Обращение к ne.transform.position без pcall вызовет краш скрипта.
  • Засорение худов и локов: Если скрипт перегружается, а метод Server:Stop() не очищает показанные игрокам меню и глобальные локи чата — интерфейс сервера ломается.
  • Очистка инвентаря: Метод DropAndResetInventory() выдаст игроку стандартное оружие спавна (пистолет). Если нужно оставить игрока только с ножом — выдайте ему C4 через GiveCmd.

Рекомендуемая структура файла (Шаблон):

lua
-- 1. CONFIG
-- 2. STATE
-- 3. GLOBAL ROUTER
-- 4. FORWARD DECLARATIONS
-- 5. UTILS
-- 6. HUD/SOUND HELPERS
-- 7. CORE LOGIC
-- 8. COROUTINES
-- 9. SERVER EVENTS

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

Информация

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

Сколько вы хотите добавить?