Next, I had the theory that maybe the game was checking the source IP address of the packet to see it if matched the expected player's address based on the DirectPlay protocol phase.
So I added the following #iptables rule such that any traffic coming from the host towards Sarah's VM (192.168.1.242) would appear as if had come from James' VM (192.168.1.243).
iptables -t nat -A POSTROUTING -p udp -s <my ip> -d 192.168.1.242 -j SNAT --to-source 192.168.1.243
In the packet captures I could see that the source IP changed as intended and Sarah's game responded to these messages, but no trains were produced.