Работа с плагинами
Полное руководство по Plugin API и серверным Lua-скриптам KONTRA FPS
Данная страница содержит исчерпывающее руководство по работе с Plugin API для KONTRA FPS. Документация базируется на официальном API движка (C# → Lua wrapper) и подтверждённых на практике архитектурных паттернах. Этот документ обязателен к ознакомлению для разработчиков серверных систем.
- 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 (Сессия / Аккаунт)
Хранит метаданные, которые существуют, даже если игрок мёртв или находится в спектраторах.
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 (Энтити / Персонаж)
Существует только когда игрок заспавнен. Если игрок мёртв или в спектраторах, методы могут выдавать ошибку или объект может отсутствовать.
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
Паттерн безопасного поиска игрока:
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.
Ключевые события:
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):
0—waitingForPlayers(ожидание)1—warmUp(разминка)6—matchActive(Основное состояние для выполнения геймплейной логики)8—matchEnd(конец раунда/матча)10—mapVoting(голосование за карту)
4. Интерфейс (HUD) и Система меню
Вся отрисовка UI работает через ServerSendNetLib.EventMessage с использованием HTML-тегов форматирования.
Отрисовка текста на экране:
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 Menu110–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 корутины являются стандартом для создания задержек, кулдаунов и периодических проверок.
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 и с задержкой, если оно следует сразу за спавном или сменой команды.
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:
ServerSendNetLib.AdditiveVelocity(peer, ne.LatestTick, Vector3Int(0, 500, 0))
ServerSendNetLib.OverrideVelocity(peer, ne.LatestTick, Vector3Int(0, 0, 0))
7. Встроенная база данных SQLite
В API встроена нативная поддержка SQLite для сохранения статистики, банов, инвентаря и т.д.
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)
pcall(function()
Server.RegisterCustomSound({"mysound.mp3", "level_up.mp3"})
end)
Воспроизведение
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.
Рекомендуемая структура файла (Шаблон):
-- 1. CONFIG
-- 2. STATE
-- 3. GLOBAL ROUTER
-- 4. FORWARD DECLARATIONS
-- 5. UTILS
-- 6. HUD/SOUND HELPERS
-- 7. CORE LOGIC
-- 8. COROUTINES
-- 9. SERVER EVENTS
Следуя этим правилам, вы обеспечите стабильную работу сервера без утечек памяти, падений логики и конфликтов с другими установленными плагинами.