When rematching, some users have a convention that e.g. lowest scoring
player in the "parent" game goes first. So allow that, providing the
choice on each rematch until a default has been chosen. Support
changing that default in a new prefs setting.
The place I chose to enforce the order was on the host as invitees are
registering and being assigned slots. But by then there's no longer
any connection to the game that was rematched, e.g. to use its
scores. So during the rematched game creation process I create and
store with the new game the necessary ordering information. For the
3-and-4 device case, it was also necessary to tweak the information
about other guests that the host sends guests (added during earlier
work on rematching.)
Android has lots of games on a single device. My current test has one
device per game. I'm hoping to fix that, and am starting with figuring
out how the script and "device" instances will communicate.
Was dropping invitations that were posted before I connected to the
remote broker. Now they're kept, and sent until the broker says
publish succeeded. Better would be to have comms resend when mqtt
connects, but I'm not set up for that.
Server needs to not rematch if any device has more than one
player (for now, as I'm too lazy to fix this rare condition.) I'm
moving toward having the linux client write status to a unix socket on
exit rather than having the test script parse the log file for
status. GameOver is there now. Tile counts should follow.
Add new script param setting a timeout before which games will be
rematched on finishing. Add new param to ncurses version telling it to
try to rematch when finishing. This introduces a new problem because
now there are multiple games per "device", and various log-grepping
stuff like listing the number of tiles in play or determing whether
device is finished all assumed one game. I addressed the latter by
adding a way to query the DB to see if all games are done, but that's
not quite right because the number of pending messages is increasing
after a game completes. Still, the testing is useful so I'm pushing
this.
Because only the host/inviter knows the addresses of all the devices
in a game it's hard for guests to rematch (unless it's a 2-device
game, as they know the host's address.) So now, as part of telling
guests the game is ready to play, include the addresses of other
guests. It's usually only 9 bytes per device, and only happens when
more than two devices are in a game.
No point in sending the old-topic-format MQTT messages to clients that
know about the new one, and in fact it's harmful. Devices in a game
already agree on the stream version to use and communicate it, so pass
that into comms once it's known and from there on to the device code
that builds mqtt messages.
This is probably a temporary fix for Linux not being aggressive enough
about calling comms_resendAll() when opening a game. For now, though,
test scripts fail without it.
To prevent deleted games' ghost invitations from remaining as
persisted on a topic and so being received over and over, have
recipient of invitation send an empty message on the same topic to
remove them. Any message sent once the game start would have replaced
the invitation, but sometimes if the sender is deleted at the right
time there's none.
I'm looking for a test case to reproduce the Andorid situation where
invitations are never deleted from comms' queue and so prevent the
game from being considered over. Doesn't seem to happen in Linux, but
more tests are good.
This should complete sending to multiple topics (for backwards
compatibility) and supporting combined messages in the future (sending
them is hard; receiving not so much.)
I didn't understand MQTT at all. Per the docs anyway it only keeps a
message around if its "persist" flag is set, and then it only keeps
the most recent per topic. I expected that when a device connected,
messages would be waiting for it, but that's apparently not true (some
evidence to the contrary.) But having all games on a device share the
same topic means only one message can be waiting. So switch to
including gameID in the topic, subscribing to a wildcard topic and
sending to a different one per game. For now, for legacy purposes,
we'll keep sending to the old per-device topic.
Duplicate messages early on, which happened only in the test script
but could have anywhere, broke connectivity. So don't kill address
records when a duplicate shows up. Dupes only escape message ID
checking early (before channel is established). I used to remove
address records when a message was rejected, but don't understand why
so removed that, though asserts show it's not mattering except for
those early messages.
Add dutil proc haveGame() and use it to detect duplicate
invitations. I'm passing, but ignoring on android, the channel, which
means that for now you can't invite yourself and on-device testing
requires having CrossWords and CrossDbg or a second user.
There was some confusion around host and self addresses, where they're
created, default values, removing conTypes from defaults that are not
in received host addr, etc. I left in some asserts to help understand
if code that seems wrong but hard to fix is still getting called.
Remove legacy relay-inspired logic around comms addressing. Now when a
device creates a game it's required to provide its "self address," and
if it's a client, the address of the host (which it presumably got
through the invitation in response to which the game is being
created.) Then as registration messages come in from clients, the host
gathers their addresses as always.
Removed a boolean that seemed unnecessary. Stopped showing
move-explanations for robots in duplicate mode. They were being shown
too early thanks to bad logic, but I don't think there's any call for
them at all. A robot's move is only interesting if it's the one that
wins the turn.
The assertion's clearly blocking testing, but I'm not sure it's not an
error for two move explanations to want to co-exist. For now they're
concatenated.
Got rid of pre-cairo drawing stuff, but that didn't fix drawing not
happening without something like a window resize to force it. Instead
I added a manual gtk_widget_queue_draw() call. It's gross, but I'm
this app's only user. :-)