I’m posting here a broad overview of my current thinking on the VASSAL 4 architecture. I realize this is vague in parts. I’m trying to avoid implementation details as much as possible, as those tend to derail design discussions. I also hate writing this kind of thing, as (a) I know that it does not explain well what I have in mind, but (b) I do not know in what ways it fails to explain what I have in mind. In order to clarify what I’m proposing and to find potential flaws, I ask that everyone read this document and comment on it. Think about how the architecture would affect you, about whether you have use cases I have not considered, about places where malicious users could cause trouble, etc.
The document is posted below, or available as a PDF if you prefer.
1 Design overview
The description here is purposely abstract, in order to give an idea of the shape of the plan without wandering off into the weeds of implementation details.
We define a game representation language for specifying game components, game history, game state, and changes to game state. The game engine API provides functions for loading game components, history, and state; for applying state changes and reporting their results; and for inspecting the current state. A game server implements the game engine API, and talks to clients using it.
Clients wanting to play in real-time find each other by registering themselves with one or more meetup servers. Clients wishing to store game history or state online for real-time or asynchronous play can do so using a storage server.
We define a game presentation language for associating game components with their visual representations. Graphical clients may use this information for displaying a graphical representation of game state with which users may interact. A complete game module would consist of a description of the rules-relevant features of the game components using the game representation language and a description of the visual features of the game components using the game presentation language.
There will be converters for producing VASSAL 4 game modules from game modules in other formats.
2 Game representation language
The game description language provides a method for defining all rules-relevant game components—pieces and their properties, piece faces and their properties, maps and locations and features on them—and their visibility to the players, as well as the game state and changes to it, which together comprise the game history.
∙ Scripting: Scripts can be attached to game objects to automate a series of changes.
3 Game engine API
The game engine API specifies methods for interacting with the game state and game history. Provided will be methods for querying the properties of pieces and maps visible to each player; for getting and setting where in the history the next change will be inserted; for applying new changes to the history.
∙ Keeping the game engine API as simple as possible will make implementing it (as a game server) and clients which use it easier.
4 Game server
A game server implements the game engine API and fulfills requests for clients. Clients will be encouraged to use locally-hosted game servers if possible, but we will maintain a public game server for situations when there is no client capable of hosting a game server.
∙ In order to avoid our public game server being a singe point of failure, we could provide clients with an updatable list of public game servers, similar to the list of meetup servers described below.
∙ Clients can coordinate with each other to determine what game server should be used, as follows: Each client joining a game attempts to connect to each other client. Any client which is capable of having an open connection with all other clients is capable of hosting the game server for that game. The clients can then elect one such to run the game server.
∙ Should the client hosting the game server drop out, how do the remaining clients recover, in the case where the game server was holding data not visible to all players? There seems to be a tension here between robustness and data visibility.
∙ A game server may additionally need to track ephemera not part of the game state and notify interested clients when these things change. A possible example of something which should not be logged but might be of interest to clients is cursor location. This should not be considered as part of the game engine API, but possibly as part of some simple client data API to which clients may subscribe (or ignore, as it has no effect on state or history).
∙ Since a client will not have data not visible to it, how will we handle recovery of game history if a player becomes unavailable?
∙ Similarly, we need some way to ensure that full game history can become available when games end.
5 Meetup server
A meetup server maintains a list of username-IP address-game name-module hash tuples which clients may query or add to. A meetup server may periodically expire these tuples.
∙ When a client connects to a meetup server, what it’s doing is saying ”hey, I’m here”: The client tells the meetup server its IP address, along with a game name and a module hash. When a client asks a meetup server who is connected, these records are returned.
∙ Clients will be expected to have a built-in default list of meetup servers, which the user can modify. This way, all a client needs to do to find other clients is ask each meetup server it knows about for the list of player it has.
∙ If one meetup server is down, there’s no problem, since presumably there would be more than one in operation.
∙ We could offer clients the opportunity to update their default list of meetup servers from our own web server—that would be a single point of failure, but only for updating the list, not for connecting to a meetup server.
∙ Each meetup server could have a group: Either it would be part of the official public ones, or part of some other public group, or part of a private group which would require a username and password for connections.
∙ Should meetup servers also facilitate chat, or should that be done through some other mechanism?
∙ Should meetup servers also facilitate posting of persistent notices? Server-wide? Module-specific? For finding opponents? Directed at particular users? Should this be done through a different mechanism or not at all?
6 Storage server
A storage server will store game history for clients and make it accessible to them over the internet. Use cases are games with more than two players, and games played by the same user on different devices—situations where distributing logs or save files by email could be onerous. A storage server needs to provide a methods for setting and retrieving data, and possibly also deleting it.
∙ No authentication is necessary if data is identified with keys of sufficient length to make them unguessable—however, we might still want user accounts in order to set per-user storage limits.
∙ We would want to temporarily block IPs which make several consecutive requests for non-existent keys, to thwart brute-force searches of the key space.
∙ Incoming data should be validated to ensure that we don’t end up storing arbitrary junk.
∙ Should stored data expire? If so, how to notify the user of this in order to prevent data loss?
∙ Could we increase robustness by having storage serves in multiple locations, all of which use a distributed hash table for storage?
A game client will send changes to and receive changes from a game server. A client may use definitions from the game presentation language to provide a graphical representation of the game state.
∙ The game server handles calculating the effects of changes on the game state. Clients need not do this themselves, which should ease implementation of clients.
∙ Clients will not have any hidden information not available to the player using them.
8 Game presentation language
The game presentation language provides a method for mapping objects defined in the game representation language to graphical assets.
∙ Clients can use the game state and definitions expressed in the game presentation language to display game state graphically.
There are four file formats which we should aim to convert to the V4 file format:
VASSAL 3.2 The proposed module format is new, not an extension of the existing V3.2 module format. In order to make use of the large library of modules VASSAL has now, we must provide a module converter. It should be possible to programmatically convert any module which does not contain custom code so long as we ensure that each V3.2 module component maps to some structure in the new game language format. Modules containing custom Java classes will not be manually convertible, at least not in their entirety, as we have no way of determining programmatically what the custom classes do. This should still allow us to convert the vast majority of modules automatically.
Aide de Camp 2 Michael Kiefte reverse-engineered the Aide de Camp 2 format and wrote converter for which is in V3.2. Presently the converter code is the only available documentation of the ADC2 format. We (probably Michael) need to document the ADC2 format, and use that to write a converter which produces V4 output instead of V3.2 output.
ZunTzu ZunTzu stores its game modules in a simple XML format. Converting this to V4 should be trivial.
CyberBoard Michael Kiefte is reverse-engineering and documenting the CybyerBoard gamebox format. We need to write a converter using this information.
∙ Converters can be standalone programs, and need not be part of any particular client.
∙ For any given module, conversion is a one-time task. Converters need not run everywhere clients do. E.g., if we don’t provide converters for use on tablets, that’s fine. Users can convert on a real computer.
∙ The ADC2 and CyberBoard converters will involve reading and manipulating binary data into something structured, as well as writing images as PNGs, and as such are best suited for C++.
∙ It might be possible to do the ZunTzu converter largely, or even entirely, using XSLT, since we would be converting one XML format to another.
∙ The ZunTzu converter is the one I intend to complete first, as soon as we have an initial draft of the game representation language, as it will provide an easy source of ready-made modules for testing purposes.
∙ We need to create some simple test modules for each converter in order that we can create acceptance tests for the converters.