Skip to content

Lobby Protocol Modification Proposal part 1: introducing a generic way to send battle data

Yaribz edited this page Mar 15, 2020 · 7 revisions

Why this proposal ?

Currently lots of different commands are used to set/update/remove/transmit battle data: SETSCRIPTTAGS/REMOVESCRIPTTAGS, DISABLEUNITS/ENABLEUNITS/ENABLEALLUNITS, ADDSTARTRECT/REMOVESTARTRECT... All these data work the same way: they are set by the host, stored in memory by the lobby server, sent automatically to any new client joining the battle and sent to all the clients in the battle when they are updated by the host. Factorizing these commands into a few more generic commands would simplify the protocol, improve extensibility and ease code factorization. These reasons alone might not be sufficient to justify refactoring a protocol which already works as it is, however the autohost system would also benefit from being able to transmit host-specific battle data the same way. Instead of adding yet another couple of commands to the lobby protocol for this, it might be a good opportunity to replace all these specific commands by a few generic ones.

In addition:

  • The SETSCRIPTTAGS/REMOVESCRIPTTAGS commands names aren't as relevant as they used to be (the lobby clients no longer generate a start script containing these tags, only the host is)
  • The SETSCRIPTTAGS/REMOVESCRIPTTAGS commands are (ab)used to send battle data which aren't written even in the host startscript.
  • The DISABLEUNITS/ENABLEUNITS/ENABLEALLUNITS commands only allow disabling units entirely. They don't allow setting a limit number, although the functionality is available in the Spring engine.
  • The ADDSTARTRECT/REMOVESTARTRECT commands don't allow removing all the start rectangles in one shot (very useful when map is changed), instead the host needs to send as many REMOVESTARTRECT commands as existing start boxes (with correct team indexes...)
  • Similarly, for example there is no way to clear all the map options with a simple command (also very useful when map is changed), instead all the existing map options need to be sent as REMOVESCRIPTTAGS parameters

How to improve the situation ?

By replacing the 7 commands listed previously (SETSCRIPTTAGS/REMOVESCRIPTTAGS, DISABLEUNITS/ENABLEUNITS/ENABLEALLUNITS and ADDSTARTRECT/REMOVESTARTRECT) by 2 more generic commands: SETBATTLEDATA/REMOVEBATTLEDATA.

The SETBATTLEDATA/REMOVEBATTLEDATA commands would work quite the same as the existing SETSCRIPTTAGS/REMOVESCRIPTTAGS commands except they would take an additional "category" parameter as first parameter.

Syntax (using Spring lobby protocol description format):

SETBATTLEDATA category {pair1} [{pair2}] [{pair3}] [{...}]

REMOVEBATTLEDATA category [key1] [key2] [...]

Allowed values for "category" parameter: "ModOptions", "MapOptions", "EngineOptions", "UnitLimits", "StartRects", "Host"

  • category=ModOptions : for all data which are currently sent using "SETSCRIPTTAGS game/modoptions/..." (i.e. only data consistent with current game according to unitsync)
  • category=MapOptions : for all data which are currently sent using "SETSCRIPTTAGS game/mapoptions/..." (i.e. only data consistent with current map according to unitsync)
  • category=EngineOptions : for all data which are currently sent using "SETSCRIPTTAGS game/..." (only "StartPosType" and "GameStartDelay" afaik ?)
  • category=UnitLimits : for all units limits which are currently managed using DISABLEUNITS/ENABLEUNITS/ENABLEALLUNITS commands (i.e. only unit names consistent with current mod according to unitsync)
  • category=StartRects : for all data which are currently managed with ADDSTARTRECT/REMOVESTARTRECT commands
  • category=Host : for host settings such as important autohost parameters which are useful to clients (the allowed host settings could be restricted at uberserver level and require approval)

For all categories except "StartRects" and "Host", maybe uberserver should convert the keys and values to lowercase (to keep same behavior as previously with SETSCRIPTTAGS). If no key parameter is provided when using REMOVEBATTLEDATA command, all the keys for the specified category are removed.

Examples: (<SP> = space character, <TAB> = tabulation character)

SETBATTLEDATA <SP> ModOptions <SP> startmetal=1000 <TAB> betterunitmovement=disabled
SETBATTLEDATA <SP> UnitLimits <SP> armflea=50
SETBATTLEDATA <SP> Host <SP> type=autohost:SPADS <TAB> mode=TeamFFA
SETBATTLEDATA <SP> StartRects <SP> allyTeam2=0 160 40 200 <TAB> allyTeam3=160 0 200 40
REMOVEBATTLEDATA <SP> StartRects
REMOVEBATTLEDATA <SP> StartRects <SP> allyTeam2 <SP> allyTeam3

Note:

The JSON format could also be used instead of the key=value list format, but the data structure managed here is actually very simple so I'm not sure there would be any benefit.

How to manage the transition ?

As usual when adding new lobby commands, a new compatibility flag should be introduced in the lobby protocol to allow lobby clients to indicate they support the new commands (SETBATTLEDATA/REMOVEBATTLEDATA).

Backward compatibility:

Ideally, it should be possible to maintain total backward compatibility for legacy battle data categories ("ModOptions", "MapOptions", "EngineOptions", "UnitLimits" and "StartRects") when implementing these new commands in uberserver. For new battle data categories however ("Host" and any battle data category which could be added in the future), the data should simply not be sent to old lobby clients not supporting the new commands.

The way the battle data have been sent by lobby clients (using old or new commands) shouldn't have any impact on the way uberserver stores these battle data in memory. Both commands sets should alter the same data in uberserver memory. When uberserver needs to send battle data to a client (when the data have been changed or when a new client joins the battle), it could just check the compatibility flag of this client and choose the commands to use to send the data accordingly. That way, both clients using the old commands and clients using the new ones can be in the same battle lobby transparently.

Forward compatibility / Extensibility:

The new generic commands will make it possible to add easily new battle data in the future in a backward compatible way (new battle data for the "Host" category, and possibly even new categories of battle data if needed). However, this means lobby clients implementing these new generic battle data management commands (SETBATTLEDATA/REMOVEBATTLEDATA) must already expect receiving unknown data in the future and silently ignore them.

For example, a new battle data "ActivePreset" for the "Host" category could be added in the future to allow lobby clients to show the currently active autohost preset in their GUI. However we don't want to force lobby clients to implement this feature and we don't want the user to see any warning if this feature isn't implemented yet in their lobby client.

To sum up:

  • For "ModOptions", "MapOptions", "EngineOptions", "UnitLimits" and "StartRects" battle data categories, the lobby clients can check the data are known and consistent (as they used to do with previous commands). If something is unexpected, the lobby clients can generate warnings to the user.
  • For "Host" or unknown battle data categories, the lobby clients should simply ignore unknown battle data.