OGame 0.84 Open Source Modification Developer Manual — API, hooks, examples
Docs Русский Wiki (MD) Example mods

Modification Developer Manual

Modifications (mods) extend the game without changing the source code of the base engine. A mod is a self-contained folder in game/mods/ containing a class that inherits GameMod (core: game/core/mods.php), metadata, localization, pages and resources.

The repository hosts four reference mods:

ModWhat it teaches
BogusModThe minimum: a DB column, an own resource, a menu item, a page, a periodic event
GalaxyToolA tool: in-game page + admin panel section, 6 languages
SpaceStormA new building, edits to global tables, economy and battle hooks, tests
DeepSpaceHorrorCustom galaxy objects, new units, custom fleet missions, tests

The full version of this document is on the project wiki: wiki/en/mods.md and wiki/ru/mods.md.

2. Mod folder structure

PathPurpose
main.phpRequired. Mod constants and the class <ИмяМода> extends GameMod
manifest.jsonRequired. Metadata for the admin panel
Readme.mdMod description (as in DeepSpaceHorror/Readme.md)
img/bg.pngBackground image (600×200) of the mod's card in the admin panel
loca/<lang>_<lang>/…Mod localization
pages/, pages_admin/PHP files of in-game and admin pages
testing/The mod's own PHPUnit test suite
Folders with sources (pages/, pages_admin/, loca/) are closed off from the browser by the .htaccess file: Order allow,deny  Deny from all. The img/ folder stays open — pages link to it.

3. manifest.json

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

Based on this data the admin panel builds the mod's card (the ModsGetInfo function). If manifest.json is missing, the mod is considered invalid and is removed from the list.

4. main.php and the GameMod class

The class name equals the folder name capitalized (ModInitOne applies ucfirst($modname)). Three required methods:

MethodWhenWhat it does
install()once, on activationDB columns/tables (ALTER TABLE under LockTables()), own queue events
uninstall()once, on deactivationremoves its columns, events, objects
init()every request while the mod is activeloca_add(); supplements the engine's global tables
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();
}

Global tables the mod supplements in init()

Declared in game/core/techs.php and game/core/prod.php.

VariableContents
$buildmap / $resmap / $fleetmap / $defmap / $rakmapIDs of buildings / research / ships / defence / missiles
$initialObject costs: $initial[GID] = [GID_RC_METAL=>…, 'factor'=>N]
$UnitParamUnit characteristics: [structure, shield, attack, cargo, speed, consumption]
$RapidFireRapid fire: $RapidFire[$gid][$target] = N
$requirementsRequirement tree: $requirements[GID] = [GID_B_RES_LAB=>3]
$CanBuildTabWhat to build for an object type: $CanBuildTab[PTYP_PLANET][] = GID
$PlanetProdProduction/consumption rules per object

Example — 'adding a building' (from SpaceStorm): a column in planets (install), the same column in install_tabs_included(), in init()$buildmap[], $initial[], $requirements[], $CanBuildTab[]; loca keys NAME_<GID> / LONG_<GID>; the image via get_object_image().

5. Mod pages

The game router is the JSON file game/router.json. The route hook is called in game/index.php after the router is loaded:

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

Router record keys: path, loca[] (required); external (page for guests), menu/header (hide the left menu/top bar), bare (no frame), mvc (the page is a Page class), admin_update_queue, update_activity, redirect_page/redirect_sec. By default a page with a session gets the standard game frame.

A classic page file is simply included by the engine; the globals $now, $aktplanet, $session, $GlobalUser, $GlobalUni, $PageMessage, $PageError are available. Example — the entire pages/tipoftheday.php file from BogusMod:

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

The admin panel has its own router, pages_admin/admin_router.json; a mod adds sections via the route_admin hook, the page class is called Admin_<Раздел> and inherits Page (example: GalaxyTool/pages_admin/admin_galaxytool.php).

6. Localization

Localization sections are loaded via loca_add($section, $lang, $dir); for a mod the third parameter is __DIR__, files reside in 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"] = "Совет дня";
?>

Reading: loca($key) (current language) and loca_lang($key, $lang). Game object names are the keys NAME_<GID> / LONG_<GID>; it is better to prefix your own keys with the mod name (STORM_*, LEVI_*).

7. Queue events

All time-based logic runs through the event queue (table queue, game/core/queue.php). API: AddQueue(), RemoveQueue(), ProlongQueue(). An event whose type is unknown to the core is passed to the update_queue hook; if no mod handled it, the event is removed with an entry written to the log.

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;                                        // не наше — дальше по списку
}

Global events are created on the technical account USER_SPACE. Queue processing is triggered by player actions and cron.php.

8. Hooks

8.1. Mechanism and rules

Hooks are GameMod methods called by the core. They run for all active mods in activation order; the first one returning true stops the chain (false means 'continue'). Reference parameters are output data. All hook declarations: game/core/mods.php.

8.2. Menus, resources, bonuses

add_menuitems(&$json) — an item of the left menu (types: 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) — a resource in the resource panel (entry: skin, img, loca, val, color); add_bonuses(&$bonuses) — a bonus in the header (entry: href, img, alt, overlib).

8.3–8.4. Content and page hooks

begin_content()/end_content() — echo before/after the page content. The page_* hooks:

HookWhat it allows
page_buildings_get_bonus($id, &$bonuses)extra bonuses of an object on the buildings/info pages
page_flotten1_get_bonus($param, &$bonuses)bonuses of the first fleet page
page_flotten2_planet_types(&$types) / page_flottenversand_ajax_spy_planets(&$types)fleet and espionage target types
page_galaxy_custom_object($planet, &$info)custom galaxy object: $info['overlib'] + true
page_infos($id, &$planet)extra info of an object (may echo)
page_overview_get_bonus($param, &$bonuses) / page_resources_get_bonus($param, &$bonuses)bonuses of the overview and 'Resources' pages

8.5. Images

get_object_image($id, &$img) (object 120×120), get_planet_small_image($type, &$img), get_planet_image($type, &$img) — return your own path in $img['path'] and true. Galaxy object types are in game/core/defs.php; types >= PTYP_CUSTOM (20001) are reserved for mod objects.

8.6. Economy

bonus_prod($param, &$bonus)/bonus_cons(...) — the mod adds a multiplier to the factor list ($param contains uni, user, planet, rc); prod_post_process(&$planet, &$eco) — post-processing of balances.

8.7. Buildings and research

can_build(&$info)/can_research(&$info) — after the standard checks; to forbid: $info['result'] = 'ключ_ошибки'; return true;. build_end($planet_id, &$queue)/research_end(&$queue) — completion of a build/research.

8.8. Fleet and espionage

fleet_available_missions($param, &$missions) — mission list; bonus_fleet_speed/bonus_fleet_cons/bonus_max_fleet — modify $bonus['value']; bonus_technology($id, &$bonus) — modifies $bonus['level'] (espionage); spy_protection($args, &$bonus) — target protection ($args['planet'], $args['target_user']).

fleet_handler($param)custom fleet missions: fires for missions unknown to the core (>= FTYP_CUSTOM, 1000) from Queue_Fleet_End. $param contains queue, fleet_obj, fleet, origin, target. Return true if the mission is yours. After the call the core removes the fleet row and the event — if the mission must continue (return trip), create a new fleet/event yourself.

8.9. Battle

battle_unit_stats($args, &$unit_param) — scaling of unit characteristics for a specific battle (changes are temporary and restored right after serialization); battle_post_process(&$res) — after the battle (result, rounds, $res['extra']).

8.10. Database

install_tabs_included(&$tabs) — declare the mod's columns in the schema (game/core/install_tabs.php): $tabs['users']['tritium'] = 'INT DEFAULT 0';. add_db_row(&$row, $tabname) — add fields when inserting via AddDBRow; lock_tables(&$tabs) — tables to lock. dbquery()/dbrows()/dbarray() are available; do not forget the $db_prefix prefix.

9. Advanced scenarios

Custom galaxy objects (DeepSpaceHorror)

An object is a regular planets row with type >= PTYP_CUSTOM, the owner is USER_SPACE; the galaxy renders it in a separate column (EnumCustomPlanetsGalaxy, ShowCustomObjects). The mod defines types/units/mission via constants, creates objects in install(), registers units in init(), provides images via hooks, shows overlib via the page_galaxy_custom_object hook, handles the battle in fleet_handler and respawning via a queue event.

Tool mod (GalaxyTool)

Its own player page + an admin panel section (Admin_GalaxyTool) + the uni.galaxytool_update column + a weekly event that rebuilds galaxy snapshots.

Cheat sheet — 'how to add…'

I wantWhat to do
A resource counterDB column + add_resources + accrual event
A buildingplanets column + install_tabs_included + $buildmap/$initial/$requirements/$CanBuildTab + loca keys + image
A ship / defencefleet columns + $fleetmap/$UnitParam/$RapidFire
A galaxy objecttype >= PTYP_CUSTOM + a USER_SPACE planet + image/galaxy hooks
A pageroute + add_menuitems + loca keys
An admin panel sectionroute_admin + the Admin_<Mode> class
A periodic actionAddQueue + update_queue + ProlongQueue

10. Testing

A mod carries its own PHPUnit test suite in testing/ (as done in SpaceStorm and DeepSpaceHorror):

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

bootstrap.php includes vendor/autoload.php, sets DB_CONNECTION=sqlite/DB_DATABASE=:memory:, does chdir into game/ and includes core/core.php and the mod's main.php. To run:

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

DB tests build a minimal universe with real functions (CreateDBTables(), AddDBRow()). 'Randomness' is moved into overridable methods (e.g. Rnd() in DeepSpaceHorror).

11. Publishing and maintenance

  • Readme.md inside the mod — description, installation, rules, hook list (sample: DeepSpaceHorror/Readme.md);
  • Version — in manifest.json; plan the DB migration when the schema changes;
  • Deactivationuninstall() returns the game to its original state;
  • Compatibility — engine 0.84, core version $CoreVersion.

12. Admin panel and management functions

The Mods section of the admin panel (admin_mods.php): installed mods on the left (order = hook activation order), available ones on the right; the mod card — the img/bg.png background and metadata:

Mod management panel in the admin panel

Management functions (game/core/mods.php): ModsInit(), ModInitOne(), ModInstallOne(), ModsInstall(), ModsRemove(), ModsMoveUp()/ModsMoveDown(), ModsList(), ModsGetInfo().

Hook dispatchers: ModsExec, ModsExecArr, ModsExecRef, ModsExecRefArr, ModsExecArrRef, ModsExecRefRef, ModsExecIntRef, ModsExecRefStr — iterate mods in activation order and stop at the first true.

13. Hook reference table

HookCall point in the coreMeaning
routeindex.phpgame pages
route_adminpages_admin/admin.phpadmin panel sections
update_queuequeue.phpcustom queue events
add_resourcespage.phpresource panel
add_menuitemspage.phpleft menu
add_bonusespage.phpbonuses in the header
lock_tablesdb_mysql.php/db_sqlite.phptables to lock
install_tabs_includeddb.php, admin_db.phpmod DB schema
get_planet_small_image / get_planet_image / get_object_imagepage.phpobject images
begin_content / end_contentpage.phpcontent before/after the page
add_db_rowdb_mysql.php/db_sqlite.phpextra fields of the inserted row
can_build / can_researchqueue.phpforbid/allow
build_end / research_endqueue.phpbuild/research completion
fleet_available_missionsfleet.phpfleet mission list
fleet_handlerfleet.phpcustom fleet mission
prod_post_processprod.phpproduction post-processing
battle_post_process / battle_unit_statsbattle.phpbattle: after / before (unit parameters)
page_buildings_get_bonusbuildings.php, b_building.phpobject bonuses
page_flotten1_get_bonusflotten1.phpfleet bonuses (step 1)
page_flotten2_planet_typesflotten2.phpfleet target types
page_flottenversand_ajax_spy_planetsflottenversand_ajax.phpespionage target types (AJAX)
page_infosinfos.phpobject info
page_galaxy_custom_objectgalaxy.phpmod galaxy objects
page_overview_get_bonus / page_resources_get_bonusoverview.php / resources.phppage bonuses
bonus_technologyfleet.php, event_list.phptechnology level
spy_protectionfleet.phpprotection from espionage
bonus_prod / bonus_consprod.phpproduction/consumption multipliers
bonus_max_fleet / bonus_fleet_cons / bonus_fleet_speedfleet.phpfleet: maximum/consumption/speed

All hook declarations with parameter descriptions are in the GameMod class (game/core/mods.php). This page is a condensed version of wiki/en/mods.md.