Big Picture
Here's a description of how the BF2 engine interacts with Python code:
- When BF2 engine starts up it fires up its embedded Python interpreter, with it's
sys.path
set to include- The Python standard library (which is contained in the file
Battlefield 2 Server/pylib-2.3.4.zip
). - The
Battlefield 2 Server/python
directory - The Python directory of the current mod (e.g.
Battlefield 2 Server/mods/bf2/python
). If the server switches mods, this will be changed, too. (It appears that the current BF2 game engine doesn't have the ability to switch mods automatically between rounds--that once a mod is loaded, it stays loaded and running until the server is manually stopped, reconfigured, and restarted). - The
Battlefield 2 Server/admin
directory.
- The Python standard library (which is contained in the file
- The BF2 engine imports the
bf2
package (the code for this package is located in the directoryBattlefield 2 Server/python
). - When Python imports a package, it executes the
__init__.py
module in that package. In the case of thebf2
, the __init__ module imports and instantiates the basic code and objects needed for the game, includinggame.scoringCommon
from the active mod's python directory (this appears to be the only place any mod-specific Python code gets pulled in). - The BF2 engine calls
bf2.init_module()
. That method imports thestats
modules. (Not clear why it's done this way, instead of just putting everything in the __init__ module). - The BF2 engine processes the
Battlefield 2 Server/mods/bf2/settings/ServerSettings.con
configuration file. In it's default, out-of-the-box configuration, that file has a directive that causes more Python activity:sv.adminScript "default"
causes thedefault
module in the directoryBattlefield 2 Server/admin
to be imported. This module primarily handles the RCon interface, but contains aninit()
function that, when called later by the game engine, causes theadmin.standard_admin
package to be imported. This package presently handles team autobalancing and punishing team killing ("TK"). See Admin Module for more details. - Throughout the start-up process, as packages and modules are imported into the embedded Python interpreter they are registering themselves to receive callbacks when various events occur in the BF2 engine.
- Some modules need to carry out initialization activities before each round can begin; they arrange for their initialization code to be called by registering to receive callbacks for
GameStatusChangedEvents
. When they receive such a callback and see that the game status is "PreGame
", they execute their initialization code. - When set-up is complete and the game is running, the Python code that was initialized during start-up then runs in event-driven mode, with the game engine dispatching execution to Python handlers when the events they registered for occur. When a player is killed in the game, for example, a
PlayerKilled
event fires, and any modules that registered to receive a callback for this event (for example, a module related to keeping score) will be called. - When a game round ends, it is important to know the game engine does not restart, and neither does the embedded Python interpreter--the
bf2
packages are not reimported or reinitialized. Instead, during start-up, modules that need to do end-of-round cleanup registered to receive callbacks forGameStatusChangedEvents
, and when they see the game status change to "EndGame
" they carry out their cleanup activities. - The game engine now jumps back a few steps in this process, to the point where game status changes to "
PreGame
", and pre-game initialization callback handlers are called to begin the cycle again.
Note that there is another directory of Python code in the Battlefield 2 Server
directory that does not get pulled in by the game engine: adminutils
contains source code and executables for the rotate_demo
and remoteconsole
stand-alone applications, as examples of how to write software that will interact with BF2. The fact that these are written in Python is coincidental. (The BF2 engine handles RCon and demo recording functionality internally, without using the embedded Python interpreter, although there are events connected with these functions that can be used to hook your own Python code to them).