@@ -69,6 +69,106 @@ git update-index --assume-unchanged Plugins/VisualPinball.Engine.Mpf.dll.meta
6969git 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