[FEAT] File association between .nxrp and SuperLemmix Player

Started by WillLem, March 09, 2024, 03:33:40 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

WillLem

I originally requested this as a NeoLemmix feature back in Dec 2020, and have finally got around to figuring it out! :lemcat:

If Windows file association is set for .nxrp files, clicking on them now loads the level into the SLX player, opens straight to preview screen, and loads the replay into memory. Clicking into the level from here then plays the replay. The presence of >1 level with the same ID is accounted for with a selectable list dialog, and it's possible to cancel loading from here if the user is unsure which level to select.

Here's a video to demonstrate the feature. Super chuffed with how this one has turned out.

Some concerns for further development:

Cancelling exits to Menu, but it's also possible to exit SLX entirely - it's difficult to decide which is more preferable here. I suppose it depends entirely on use case, and possibly on this:

Currently, opening multiple replay files in this manner will open multiple instances of the SLX player, each with the relevant level & replay loaded. I personally think this is OK, and I'm not 100% sure if there's a way to load directly into an currently-open instance. Might investigate this further if people think it would be worth it.

This will definitely be present in 2.7 (due end of April). Implemented in Commit 1aa6df537


WillLem

Found a tricksy bug with this today. It's now fixed (Commits 7d74ac3 and da7837e), but I thought it would be important to document the findings because it involved answering a question I'd had for a while, namely: why can't the value of GameParams.CurrentLevel be written to directly?

Here are the steps to reproduce the bug (in 2.8.2 and earlier):

0) (Make sure .nxrp files are associated with the latest SLX player)
1) Choose 2 replays from the same pack, e.g. level 2 and level 4
2) Double-click the replay for level 2 to open SLX, close SLX
3) Double-click the replay for level 4 to open SLX, open the Level Select browser

Now, in the Level Select browser, the title for level 4 will appear in place of the title for level 2. If selecting level 2 and loading it ito the player, level 4 will be loaded instead.

Previously, the method for matching the clicked replay to its relevant level was directly setting the matched level file to the value of GameParams.CurrentLevel.Filename. This was problematic because it meant that the Player was assigning the filename to whichever level had previously been assigned as CurrentLevel. Not a problem in theory, because the correct level was always loaded into the player.

However, in practice, the value of CurrentLevel was being overwritten and not reset correctly, resulting in the above bug (and, likely, several others that hadn't yet been spotted).

The fix is to assign the matched file to the similarly named but logically separate Level.Filename property and then call GameParams.SetLevel(Level), which sets the value of CurrentLevel within the correct context.

CurrentLevel is once again a read-only property, and now I understand why it should be that way; many different aspects of the program rely on this being set correctly from within existing GameParams procedures. It probably could be refactored to be directly settable from anywhere, but for now it's satisfying to have discovered the way it's meant to work in the existing codebase.

namida

Quote from: WillLem on November 28, 2024, 08:39:42 PMCurrentLevel is once again a read-only property, and now I understand why it should be that way; many different aspects of the program rely on this being set correctly from within existing GameParams procedures. It probably could be refactored to be directly settable from anywhere, but for now it's satisfying to have discovered the way it's meant to work in the existing codebase.

Solution: Specifically make it so that CurrentLevel's setter either calls, or is, GameParams.SetLevel.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

WillLem

Quote from: namida on November 30, 2024, 06:03:47 AMSolution: Specifically make it so that CurrentLevel's setter either calls, or is, GameParams.SetLevel.

I think this is already what happens. CurrentLevel reads fCurrentLevel, which is set by GameParams.SetLevel():

procedure TDosGameParams.SetLevel(aLevel: TNeoLevelEntry);
begin
  fCurrentLevel := aLevel;
end;