OGame 0.84 Open Source Руководство разработчика модификаций — API, хуки, примеры
Документация English Wiki (MD) Примеры модов

Руководство разработчика модификаций

Модификации (моды) расширяют игру, не меняя исходный код базового движка. Мод — самодостаточная папка в game/mods/, содержащая класс-наследник GameMod (ядро: game/core/mods.php), метаданные, локализацию, страницы и ресурсы.

В репозитории живут четыре эталонных мода:

МодЧему учит
BogusModМинимум: колонка БД, свой ресурс, пункт меню, страница, периодическое событие
GalaxyToolИнструмент: игровая страница + раздел админки, 6 языков
SpaceStormНовое здание, правки глобальных таблиц, экономические и боевые хуки, тесты
DeepSpaceHorrorКастомные объекты галактики, новые юниты, кастомные миссии флота, тесты

Полная версия документа — на вики проекта: wiki/ru/mods.md и wiki/en/mods.md.

2. Структура папки мода

ПутьНазначение
main.phpОбязателен. Константы мода и класс <ИмяМода> extends GameMod
manifest.jsonОбязателен. Метаданные для админки
Readme.mdОписание мода (как в DeepSpaceHorror/Readme.md)
img/bg.pngКартинка-подложка (600×200) карточки мода в админке
loca/<lang>_<lang>/…Локализация мода
pages/, pages_admin/PHP-файлы игровых и админ-страниц
testing/Собственный PHPUnit-набор мода
Папки с исходниками (pages/, pages_admin/, loca/) закрываются от браузера файлом .htaccess: Order allow,deny  Deny from all. Папка img/ остаётся открытой — на неё ссылаются страницы.

3. manifest.json

{
  "name": "My Awesome Mod",
  "version": "1.0.0",
  "author": "YourName",
  "description": "Добавляет новые возможности для игроков",
  "website": "https://github.com/yourname/mod-name"
}

По этим данным админка строит карточку мода (функция ModsGetInfo). Если manifest.json отсутствует — мод считается невалидным и убирается из списка.

4. main.php и класс GameMod

Имя класса = имя папки с заглавной буквы (ModInitOne делает ucfirst($modname)). Три обязательных метода:

МетодКогдаЧто делает
install()один раз при активацииколонки/таблицы БД (ALTER TABLE под LockTables()), свои события очереди
uninstall()один раз при деактивацииубирает свои колонки, события, объекты
init()каждый запрос, пока мод активенloca_add(); дополнение глобальных таблиц движка
public function install() : void {
    global $db_prefix;
    LockTables();
    $query = "ALTER TABLE ".$db_prefix."users ADD COLUMN tritium INT DEFAULT 0;";
    dbquery ($query);
    // своё периодическое событие, если ещё не заведено
    $query = "SELECT * FROM ".$db_prefix."queue WHERE type = '".QTYP_ADD_TRITIUM."'";
    $result = dbquery ($query);
    if ( dbrows ($result) == 0 ) {
        AddQueue (USER_SPACE, QTYP_ADD_TRITIUM, 0, 0, 0, time(), 3600);
    }
    UnlockTables();
}

Глобальные таблицы, которые мод дополняет в init()

Объявлены в game/core/techs.php и game/core/prod.php.

ПеременнаяСодержимое
$buildmap / $resmap / $fleetmap / $defmap / $rakmapID построек / исследований / кораблей / обороны / ракет
$initialСтоимость объектов: $initial[GID] = [GID_RC_METAL=>…, 'factor'=>N]
$UnitParamХарактеристики юнита: [структура, щит, атака, груз, скорость, расход]
$RapidFireСкорострел: $RapidFire[$gid][$target] = N
$requirementsДерево требований: $requirements[GID] = [GID_B_RES_LAB=>3]
$CanBuildTabЧто строить для типа объекта: $CanBuildTab[PTYP_PLANET][] = GID
$PlanetProdПравила производства/потребления по объектам

Пример — «добавить здание» (из SpaceStorm): колонка в planets (install), та же колонка в install_tabs_included(), в init()$buildmap[], $initial[], $requirements[], $CanBuildTab[]; локали NAME_<GID> / LONG_<GID>; картинка через get_object_image().

5. Страницы мода

Роутер игры — JSON game/router.json. Хук route вызывается в game/index.php после загрузки роутера:

public function route(array &$router) : bool {
    $router['tipoftheday'] = array (
        'path' => "mods/BogusMod/pages/tipoftheday.php",
        'loca' => [ "menu" ]
    );
    return false;   // не останавливаем цепочку
}

Ключи записи роутера: path, loca[] (обязательны); external (страница для гостей), menu/header (скрыть левое меню/верхнюю панель), bare (без обрамления), mvc (страница — класс Page), admin_update_queue, update_activity, redirect_page/redirect_sec. По умолчанию страница с сессией получает стандартное обрамление игры.

Классический файл страницы просто включается движком; доступны глобалы $now, $aktplanet, $session, $GlobalUser, $GlobalUni, $PageMessage, $PageError. Пример — весь файл pages/tipoftheday.php из BogusMod:

<?=loca("BOGUS_MOD_TIP1");?>

Админка — свой роутер pages_admin/admin_router.json; разделы мод добавляет хуком route_admin, класс страницы называется Admin_<Раздел> и наследует Page (пример: GalaxyTool/pages_admin/admin_galaxytool.php).

6. Локализация

Секции локали подключаются через loca_add($section, $lang, $dir); для мода третий параметр — __DIR__, файлы лежат в loca/<lang>_<lang>/<section>.php:

public function init() : void {
    global $GlobalUni;
    loca_add ("bogusmod", $GlobalUni['lang'], __DIR__);
}
<?php
$LOCA["ru"]["BOGUS_MOD_TRITIUM"]   = "Тритий";
$LOCA["ru"]["BOGUS_MOD_MENU_ITEM"] = "Совет дня";
?>

Чтение: loca($key) (текущий язык) и loca_lang($key, $lang). Имена игровых объектов — ключи NAME_<GID> / LONG_<GID>; свои ключи лучше с префиксом мода (STORM_*, LEVI_*).

7. События в очереди

Вся временная логика — очередь событий (таблица queue, game/core/queue.php). API: AddQueue(), RemoveQueue(), ProlongQueue(). Событие с незнакомым ядру type передаётся хуку update_queue; если ни один мод его не обработал — событие удаляется с записью в лог.

public function update_queue(array &$queue) : bool {
    global $db_prefix;
    if ($queue['type'] === QTYP_ADD_TRITIUM) {           // "AddTritium"
        $query = "UPDATE ".$db_prefix."users SET tritium = tritium + 1;";
        dbquery ( $query );
        ProlongQueue ($queue['task_id'], 3600);          // продлить: событие периодическое
        return true;                                     // обработано
    }
    return false;                                        // не наше — дальше по списку
}

Глобальные события заводятся на технический аккаунт USER_SPACE. Обработка очереди запускается действиями игроков и cron.php.

8. Хуки

8.1. Механизм и правила

Хуки — методы GameMod, вызываемые ядром. Они исполняются для всех активных модов в порядке активации; первый вернувший true останавливает цепочку (false — «продолжить»). Параметры-ссылки — выходные данные. Объявления всех хуков: game/core/mods.php.

8.2. Меню, ресурсы, бонусы

add_menuitems(&$json) — пункт левого меню (типы: internal, external, img, popup, internal_buggy);

public function add_menuitems(array &$json) : bool {
    array_insert_after_key ($json, "options", "tipoftheday",
        array ('type' => 'internal', 'page' => 'tipoftheday', 'loca' => 'BOGUS_MOD_MENU_ITEM') );
    return false;
}

add_resources(&$json, $planet) — ресурс в панели ресурсов (запись: skin, img, loca, val, color); add_bonuses(&$bonuses) — бонус в шапке (запись: href, img, alt, overlib).

8.3–8.4. Контент и хуки страниц

begin_content()/end_content() — echo до/после контента страницы. Хуки page_*:

ХукЧто позволяет
page_buildings_get_bonus($id, &$bonuses)доп. бонусы объекта на страницах построек/инфо
page_flotten1_get_bonus($param, &$bonuses)бонусы первой страницы флота
page_flotten2_planet_types(&$types) / page_flottenversand_ajax_spy_planets(&$types)типы целей флота и шпионажа
page_galaxy_custom_object($planet, &$info)кастомный объект галактики: $info['overlib'] + true
page_infos($id, &$planet)доп. инфо объекта (можно echo)
page_overview_get_bonus($param, &$bonuses) / page_resources_get_bonus($param, &$bonuses)бонусы обзора и «Сырья»

8.5. Изображения

get_object_image($id, &$img) (объект 120×120), get_planet_small_image($type, &$img), get_planet_image($type, &$img) — вернуть свой путь в $img['path'] и true. Типы объектов галактики — в game/core/defs.php; типы >= PTYP_CUSTOM (20001) зарезервированы для объектов модов.

8.6. Экономика

bonus_prod($param, &$bonus)/bonus_cons(...) — мод добавляет множитель в список факторов ($param содержит uni, user, planet, rc); prod_post_process(&$planet, &$eco) — пост-обработка балансов.

8.7. Постройки и исследования

can_build(&$info)/can_research(&$info) — после стандартных проверок; запрет: $info['result'] = 'ключ_ошибки'; return true;. build_end($planet_id, &$queue)/research_end(&$queue) — завершение стройки/исследования.

8.8. Флот и шпионаж

fleet_available_missions($param, &$missions) — список миссий; bonus_fleet_speed/bonus_fleet_cons/bonus_max_fleet — правят $bonus['value']; bonus_technology($id, &$bonus) — правят $bonus['level'] (шпионаж); spy_protection($args, &$bonus) — защита цели ($args['planet'], $args['target_user']).

fleet_handler($param)кастомные миссии флота: срабатывает для неизвестных ядру миссий (>= FTYP_CUSTOM, 1000) из Queue_Fleet_End. В $paramqueue, fleet_obj, fleet, origin, target. Вернуть true, если миссия ваша. После вызова ядро удаляет строку флота и событие — если миссия должна продолжаться (возврат), создавайте новый флот/событие сами.

8.9. Бой

battle_unit_stats($args, &$unit_param) — масштабирование характеристик юнитов для конкретного боя (изменения временные, восстанавливаются сразу после сериализации); battle_post_process(&$res) — после боя (результат, раунды, $res['extra']).

8.10. База данных

install_tabs_included(&$tabs) — объявить колонки мода в схеме (game/core/install_tabs.php): $tabs['users']['tritium'] = 'INT DEFAULT 0';. add_db_row(&$row, $tabname) — докинуть поля при вставке через AddDBRow; lock_tables(&$tabs) — таблицы в блокировку. Доступны dbquery()/dbrows()/dbarray(); не забывайте префикс $db_prefix.

9. Расширенные сценарии

Кастомные объекты галактики (DeepSpaceHorror)

Объект — обычная строка planets с type >= PTYP_CUSTOM, владелец — USER_SPACE; галактика рисует его отдельной колонкой (EnumCustomPlanetsGalaxy, ShowCustomObjects). Мод задаёт типы/юнитов/миссию константами, создаёт объекты в install(), регистрирует юнитов в init(), отдаёт картинки хуками, показывает overlib хуком page_galaxy_custom_object, обрабатывает бой в fleet_handler и возрождение — событием очереди.

Мод-инструмент (GalaxyTool)

Своя страница игрока + раздел админки (Admin_GalaxyTool) + колонка uni.galaxytool_update + еженедельное событие пересборки снимков галактики.

Шпаргалка «как добавить…»

ХочуЧто делать
Ресурс-счётчикколонка БД + add_resources + событие начисления
Зданиеколонка planets + install_tabs_included + $buildmap/$initial/$requirements/$CanBuildTab + локали + картинка
Корабль / оборонуколонки fleet + $fleetmap/$UnitParam/$RapidFire
Объект галактикитип >= PTYP_CUSTOM + планета USER_SPACE + хуки картинок/галактики
Страницуroute + add_menuitems + локали
Раздел админкиroute_admin + класс Admin_<Mode>
Периодическое действиеAddQueue + update_queue + ProlongQueue

10. Тестирование

Мод носит свой PHPUnit-набор в testing/ (так сделано в SpaceStorm и DeepSpaceHorror):

game/mods/<Name>/testing/
├── phpunit.xml      # конфигурация набора
├── bootstrap.php    # ядро + мод на in-memory SQLite
├── <Name>Test.php
└── <Name>DbTest.php

bootstrap.php подключает vendor/autoload.php, задаёт DB_CONNECTION=sqlite/DB_DATABASE=:memory:, делает chdir в game/ и включает core/core.php и main.php мода. Запуск:

vendor/bin/phpunit -c game/mods/SpaceStorm/testing/phpunit.xml

DB-тесты строят минимальную вселенную настоящими функциями (CreateDBTables(), AddDBRow()). «Случайность» выносится в переопределяемые методы (напр. Rnd() в DeepSpaceHorror).

11. Публикация и сопровождение

  • Readme.md внутри мода — описание, установка, правила, список хуков (образец: DeepSpaceHorror/Readme.md);
  • Версия — в manifest.json; продумайте миграцию БД при изменении схемы;
  • Деактивацияuninstall() возвращает игру в исходное состояние;
  • Совместимость — движок 0.84, версия ядра $CoreVersion.

12. Админка и функции управления

Раздел Моды админки (admin_mods.php): слева — установленные (порядок = порядок активации хуков), справа — доступные; карточка мода — фон img/bg.png и метаданные:

Панель управления модами в админке

Функции управления (game/core/mods.php): ModsInit(), ModInitOne(), ModInstallOne(), ModsInstall(), ModsRemove(), ModsMoveUp()/ModsMoveDown(), ModsList(), ModsGetInfo().

Диспетчеры хуков: ModsExec, ModsExecArr, ModsExecRef, ModsExecRefArr, ModsExecArrRef, ModsExecRefRef, ModsExecIntRef, ModsExecRefStr — обходят моды в порядке активации, останавливаются на первом true.

13. Сводная таблица хуков

ХукТочка вызова в ядреСмысл
routeindex.phpстраницы игры
route_adminpages_admin/admin.phpразделы админки
update_queuequeue.phpкастомные события очереди
add_resourcespage.phpпанель ресурсов
add_menuitemspage.phpлевое меню
add_bonusespage.phpбонусы в шапке
lock_tablesdb_mysql.php/db_sqlite.phpтаблицы в блокировку
install_tabs_includeddb.php, admin_db.phpсхема БД мода
get_planet_small_image / get_planet_image / get_object_imagepage.phpкартинки объектов
begin_content / end_contentpage.phpконтент до/после страницы
add_db_rowdb_mysql.php/db_sqlite.phpдоп. поля вставляемой строки
can_build / can_researchqueue.phpзапрет/разрешение
build_end / research_endqueue.phpзавершение стройки/исследования
fleet_available_missionsfleet.phpсписок миссий флота
fleet_handlerfleet.phpкастомная миссия флота
prod_post_processprod.phpпост-обработка производства
battle_post_process / battle_unit_statsbattle.phpбой: после / до (параметры юнитов)
page_buildings_get_bonusbuildings.php, b_building.phpбонусы объекта
page_flotten1_get_bonusflotten1.phpбонусы флота (шаг 1)
page_flotten2_planet_typesflotten2.phpтипы целей флота
page_flottenversand_ajax_spy_planetsflottenversand_ajax.phpтипы целей шпионажа (AJAX)
page_infosinfos.phpинфо объекта
page_galaxy_custom_objectgalaxy.phpобъекты галактики модов
page_overview_get_bonus / page_resources_get_bonusoverview.php / resources.phpбонусы страниц
bonus_technologyfleet.php, event_list.phpуровень технологии
spy_protectionfleet.phpзащита от шпионажа
bonus_prod / bonus_consprod.phpмножители производства/потребления
bonus_max_fleet / bonus_fleet_cons / bonus_fleet_speedfleet.phpфлот: максимум/расход/скорость

Объявления всех хуков с описанием параметров — в классе GameMod (game/core/mods.php). Эта страница — краткая версия wiki/ru/mods.md.