idea about campaign server (that works as a client)
Posted: Fri Aug 21, 2026 8:36 pm
Previous topic about playing campaigns in Freeciv
A campaign is a set of scenarios played in a flexible order according to a common script. Since Freeciv is inherently a multiplayer project, we should be able to play a campaign on several servers, some of which may be running simultaneously. A simple campaign may be an olympic-system tournament: we give the database of players to the campaign server, and it automatically forms 2^n groups of 3-4 players for the first round and then makes pairs of the winners of a previous round for thr next round until two last ones play the final match.
My idea is that the campaign server should be actually based on the common code of Freeciv clients. The differences from any normal clients are:
1) Headless client - no actual GUI (some functions can be easily integrated into the normal clients, but for some others I am not so sure). But it still knows all the client-side networking protocol and can run any client Lua scripts manipulatinc client-side game objects.
2) Several simultaneous server connections! The script would run campaign.start_server("scenario_name.sav") function that returns a Server object that stores both the process and the networking connection to it. Though, to reuse the existing client code and to keep memory use low, at maximum one of the servers is active and provides game objects and event packets. All inactively connected game servers still keep the connection to the campaign server but don't send most of the packets that a usual global observer would receive; they send only main packets like "player lost" or "game finished", as well as special "campaign message" packets that contain arbitrary information explicitly scripted within the scenarios. Receiving such packets triggers events within the campaign server and it may respond with a message for the scenarios script, or activate the connection and look at the full game picture.
3) The Lua state is not reset during the campaign server session even if it activates different games many times. Just the game objects of inactivated connection are cleared from the memory; but in Lua memory, "Unexistent" objects that replace them are not just dummy pointers but informative reference-counted records containing the object type, the object id and the server from which it was loaded. When the server is reactivated, Unexistent objects become units, players and cities again (if only they are not destroyed during the game).
4) The campaign server scripting must support client editing packets for the active connection (well, that is easily portable to normal clients). So, we can tell at one server "your enemies run away", remove units of an AI player on that server and copy them to another server, either already running with different people playing or newly started with another map for the same player. The player's units, or terrain alterations, may be transferred from a game to a game in the same manner.
5) When the scripting server ends a scenario of the campaign, it prepares a new server and sends a special packet to the server to close that informs any connected players' clients about the port where they should continue playing (maybe different players go to different servers). Something should be done to the annoying minimalization of the window of a disconnected client; maybe the message should contain some interlude narration and a background image reference to display to the player while the new connection gets ready.
6) Among other things, the campaign server tells to the game servers which players from the login database can play on them. It also can tell a server to kick a player after some trigger, with redirecting to another server or not.
7) The campaign server "client" Lua state and data about running game servers should be regulary saved for the failure risk, and the whole system should get easily resumed if needed. A way to resume certain specific points at a campaign should exist, combining loading appropriate campaign save and scenario saves simultaneously. Failure of specific game servers should be tracked as well, maybe resumed by the script itself, maybe the script should pause other running scenarios until a failed one is fixed by the game master.
8) There should better exist a mechanism for automatic HTTP portal page creation to tell disconnected players players the port numbers they should connect now, as well as specific game information, including private info for each of the players if they log on this portal. Also, some human-readable campaign history text file may be formed during the game events.
9) The campaign server may be provided with a specific script overriding the standard freeciv-server to start and connect to Freeciv servers on different machines.
A campaign is a set of scenarios played in a flexible order according to a common script. Since Freeciv is inherently a multiplayer project, we should be able to play a campaign on several servers, some of which may be running simultaneously. A simple campaign may be an olympic-system tournament: we give the database of players to the campaign server, and it automatically forms 2^n groups of 3-4 players for the first round and then makes pairs of the winners of a previous round for thr next round until two last ones play the final match.
My idea is that the campaign server should be actually based on the common code of Freeciv clients. The differences from any normal clients are:
1) Headless client - no actual GUI (some functions can be easily integrated into the normal clients, but for some others I am not so sure). But it still knows all the client-side networking protocol and can run any client Lua scripts manipulatinc client-side game objects.
2) Several simultaneous server connections! The script would run campaign.start_server("scenario_name.sav") function that returns a Server object that stores both the process and the networking connection to it. Though, to reuse the existing client code and to keep memory use low, at maximum one of the servers is active and provides game objects and event packets. All inactively connected game servers still keep the connection to the campaign server but don't send most of the packets that a usual global observer would receive; they send only main packets like "player lost" or "game finished", as well as special "campaign message" packets that contain arbitrary information explicitly scripted within the scenarios. Receiving such packets triggers events within the campaign server and it may respond with a message for the scenarios script, or activate the connection and look at the full game picture.
3) The Lua state is not reset during the campaign server session even if it activates different games many times. Just the game objects of inactivated connection are cleared from the memory; but in Lua memory, "Unexistent" objects that replace them are not just dummy pointers but informative reference-counted records containing the object type, the object id and the server from which it was loaded. When the server is reactivated, Unexistent objects become units, players and cities again (if only they are not destroyed during the game).
4) The campaign server scripting must support client editing packets for the active connection (well, that is easily portable to normal clients). So, we can tell at one server "your enemies run away", remove units of an AI player on that server and copy them to another server, either already running with different people playing or newly started with another map for the same player. The player's units, or terrain alterations, may be transferred from a game to a game in the same manner.
5) When the scripting server ends a scenario of the campaign, it prepares a new server and sends a special packet to the server to close that informs any connected players' clients about the port where they should continue playing (maybe different players go to different servers). Something should be done to the annoying minimalization of the window of a disconnected client; maybe the message should contain some interlude narration and a background image reference to display to the player while the new connection gets ready.
6) Among other things, the campaign server tells to the game servers which players from the login database can play on them. It also can tell a server to kick a player after some trigger, with redirecting to another server or not.
7) The campaign server "client" Lua state and data about running game servers should be regulary saved for the failure risk, and the whole system should get easily resumed if needed. A way to resume certain specific points at a campaign should exist, combining loading appropriate campaign save and scenario saves simultaneously. Failure of specific game servers should be tracked as well, maybe resumed by the script itself, maybe the script should pause other running scenarios until a failed one is fixed by the game master.
8) There should better exist a mechanism for automatic HTTP portal page creation to tell disconnected players players the port numbers they should connect now, as well as specific game information, including private info for each of the players if they log on this portal. Also, some human-readable campaign history text file may be formed during the game events.
9) The campaign server may be provided with a specific script overriding the standard freeciv-server to start and connect to Freeciv servers on different machines.