Skip to content

Commit 991d111

Browse files
Add design section to README.md
1 parent 6a6a0e7 commit 991d111

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,106 @@ git update-index --assume-unchanged Plugins/VisualPinball.Engine.Mpf.dll.meta
6969
git update-index --assume-unchanged Plugins/VisualPinball.Engine.Mpf.pdb.meta
7070
```
7171

72+
## Design
73+
74+
MPF is a standalone Python application and not a library. Despite this, we want
75+
to make its use with VPE as seamless as possible, so we include precompiled MPF
76+
binaries and start them together with VPE automatically. The process of starting
77+
up and communicating with MPF via gRPC while respecting the many configuration
78+
options that are available is quite complex and managed in a single class:
79+
`MpfWrangler`. It could be worthwhile to split it up into one class that manages
80+
the MPF process and another that manages the gRPC connection.
81+
82+
MPF has two APIs: One to control hardware on the playfield, and one to play
83+
media in the backbox. The former is the main, essential part of this MPF
84+
integration and the latter was added later. The hardware controller is
85+
responsible for sending switch changes to MPF and applying its commands to
86+
correct items on the playfield. This is done by the class `MpfGamelogicEngine`.
87+
It also retrieves and stores the machine description from MPF at design time,
88+
which allows the table author to create the mapping between MPF and VPE coils,
89+
lamps and switches that is used at runtime to control the playfield.
90+
91+
### MPF Binaries
92+
93+
The precompiled binaries included here are slightly different from the official
94+
version of MPF. They are based on `0.80.0.dev6`, with the addition of a _Ping_
95+
RPC that allows VPE to check whether MPF is ready without any side effects (like
96+
starting the game). This way, the game can start as soon as MPF is ready,
97+
regardless of how long MPF takes to start up. I have
98+
[proposed this change](https://github.com/missionpinball/mpf/pull/1865) to the
99+
MPF developers, but as of February 2025 they have not yet gotten around to
100+
including it in the official version. The binaries were made using
101+
[PyInstaller](https://pyinstaller.org). I'm not completely sure anymore what
102+
parameters I used, but this should be pretty close:
103+
`pyinstaller --collect-all mpf --exclude-module mpf.tests --name mpf --noconfirm mpf/**main**.py`.
104+
105+
### Media controller
106+
107+
This repository includes a basic media controller implementation that is fully
108+
compliant with the
109+
[BCP spec](https://missionpinball.org/latest/code/BCP_Protocol/) and can parse
110+
all documented message types. Without writing code, table authors can trigger
111+
sounds, toggle game objects and display variables in text fields, but its
112+
capabilities are not comparable to those of the official Kivvy and Godot based
113+
media controllers made by the MPF developers.
114+
115+
#### Connection
116+
117+
When the included media controller is selected in the game logic engine
118+
inspector, the `MpfWrangler` creates the `BcpInterface` in its constructor,
119+
which in turn creates the `BcpServer` that ultimately starts a `TcpListener` to
120+
send and receive messages from MPF via TCP. Messages are sent and received
121+
through a message queue, but the server does not run on a separate thread.
122+
123+
#### Parsing
124+
125+
To communicate with the various available media controller implementations, the
126+
MPF developers invented their own little message format called
127+
'[Backbox Control Protocol](https://missionpinball.org/latest/code/BCP_Protocol/),'
128+
or BCP for short. The downside compared to something like gRPC is that there is
129+
no parser. All we get is strings. Much of the code that comprises VPE's media
130+
controller is dedicated to parsing those message strings into strongly typed C#
131+
objects and back. For each message type, there is a class that parses and
132+
represents instances of it.
133+
134+
#### Reacting to messages
135+
136+
There is also a message handler class for each type of message that fires an
137+
event every time a message of the associated type is received. Some message
138+
types must be requested by the media controller using the
139+
[`monitor_start`](https://missionpinball.org/latest/code/BCP_Protocol/monitor_start/)
140+
command. By the number of listeners to the events of each message handler, we
141+
can tell when a message type is actually of interest and monitor only those
142+
message types.
143+
144+
#### Monitoring
145+
146+
Many BCP message types are sent when some variable in MPF changes. For easy
147+
access to these values in VPE, there are monitoring classes for these types of
148+
messages that share a common base class and provide the most recently sent value
149+
and an event that is triggered when a new value is received. For example, using
150+
the `CurrentPlayerPlayerMonitor` class, other code can easily keep track of
151+
whose turn it is without having to go through the
152+
`PlayerTurnStartMessageHandler`.
153+
154+
#### Limitations
155+
156+
To the table author, who is not really allowed to write C# code because it
157+
cannot be shipped with the table file, we offer a few Unity components that can
158+
make sounds and toggle objects based on events and modes from MPF and display
159+
player and machine variables in text fields. The sad part is that this severely
160+
limits what would otherwise be possible with this media controller
161+
implementation. Many message types are not accessible and some fairly basic
162+
functionality like displaying player variables of a player other than the
163+
currently active one is not supported. To fix this, the selection of components
164+
and their feature-set should grow and there should be a visual scripting
165+
interface for less common use-cases.
166+
167+
The most important missing feature is support for slides or more generally
168+
support for displaying stuff on the backbox display. The first obstacle here is
169+
that the way slides work in MPF is
170+
[not officially defined or documented](https://github.com/missionpinball/mpf-gmc/issues/26).
171+
72172
## License
73173

74174
[MIT](LICENSE)

0 commit comments

Comments
 (0)