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:
| Mod | What it teaches |
|---|---|
BogusMod | The minimum: a DB column, an own resource, a menu item, a page, a periodic event |
GalaxyTool | A tool: in-game page + admin panel section, 6 languages |
SpaceStorm | A new building, edits to global tables, economy and battle hooks, tests |
DeepSpaceHorror | Custom galaxy objects, new units, custom fleet missions, tests |
2. Mod folder structure
| Path | Purpose |
|---|---|
main.php | Required. Mod constants and the class <ИмяМода> extends GameMod |
manifest.json | Required. Metadata for the admin panel |
Readme.md | Mod description (as in DeepSpaceHorror/Readme.md) |
img/bg.png | Background 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.htaccessfile:Order allow,deny Deny from all. Theimg/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:
| Method | When | What it does |
|---|---|---|
install() | once, on activation | DB columns/tables (ALTER TABLE under LockTables()), own queue events |
uninstall() | once, on deactivation | removes its columns, events, objects |
init() | every request while the mod is active | loca_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.
| Variable | Contents |
|---|---|
$buildmap / $resmap / $fleetmap / $defmap / $rakmap | IDs of buildings / research / ships / defence / missiles |
$initial | Object costs: $initial[GID] = [GID_RC_METAL=>…, 'factor'=>N] |
$UnitParam | Unit characteristics: [structure, shield, attack, cargo, speed, consumption] |
$RapidFire | Rapid fire: $RapidFire[$gid][$target] = N |
$requirements | Requirement tree: $requirements[GID] = [GID_B_RES_LAB=>3] |
$CanBuildTab | What to build for an object type: $CanBuildTab[PTYP_PLANET][] = GID |
$PlanetProd | Production/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:
| Hook | What 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 want | What to do |
|---|---|
| A resource counter | DB column + add_resources + accrual event |
| A building | planets column + install_tabs_included + $buildmap/$initial/$requirements/$CanBuildTab + loca keys + image |
| A ship / defence | fleet columns + $fleetmap/$UnitParam/$RapidFire |
| A galaxy object | type >= PTYP_CUSTOM + a USER_SPACE planet + image/galaxy hooks |
| A page | route + add_menuitems + loca keys |
| An admin panel section | route_admin + the Admin_<Mode> class |
| A periodic action | AddQueue + 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; - Deactivation —
uninstall()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:
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
| Hook | Call point in the core | Meaning |
|---|---|---|
route | index.php | game pages |
route_admin | pages_admin/admin.php | admin panel sections |
update_queue | queue.php | custom queue events |
add_resources | page.php | resource panel |
add_menuitems | page.php | left menu |
add_bonuses | page.php | bonuses in the header |
lock_tables | db_mysql.php/db_sqlite.php | tables to lock |
install_tabs_included | db.php, admin_db.php | mod DB schema |
get_planet_small_image / get_planet_image / get_object_image | page.php | object images |
begin_content / end_content | page.php | content before/after the page |
add_db_row | db_mysql.php/db_sqlite.php | extra fields of the inserted row |
can_build / can_research | queue.php | forbid/allow |
build_end / research_end | queue.php | build/research completion |
fleet_available_missions | fleet.php | fleet mission list |
fleet_handler | fleet.php | custom fleet mission |
prod_post_process | prod.php | production post-processing |
battle_post_process / battle_unit_stats | battle.php | battle: after / before (unit parameters) |
page_buildings_get_bonus | buildings.php, b_building.php | object bonuses |
page_flotten1_get_bonus | flotten1.php | fleet bonuses (step 1) |
page_flotten2_planet_types | flotten2.php | fleet target types |
page_flottenversand_ajax_spy_planets | flottenversand_ajax.php | espionage target types (AJAX) |
page_infos | infos.php | object info |
page_galaxy_custom_object | galaxy.php | mod galaxy objects |
page_overview_get_bonus / page_resources_get_bonus | overview.php / resources.php | page bonuses |
bonus_technology | fleet.php, event_list.php | technology level |
spy_protection | fleet.php | protection from espionage |
bonus_prod / bonus_cons | prod.php | production/consumption multipliers |
bonus_max_fleet / bonus_fleet_cons / bonus_fleet_speed | fleet.php | fleet: 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.