The Glulx/Glk extensions ecosystem

Now that people are starting to use Zarf’s Unified Glulx Input extension, I’ve been thinking about the state of the Glulx/Glk extensions ecosystem and how it could be improved. I’ve started working on a wiki page at the i7/extensions Github repository, and I’d welcome anyone else contributing to it.

So the problem is that some of these extensions are big and incompatible, notably UGI and GEP. But something like GEP actually implements several independent features, most of which are not incompatible with UGI.

My idea is that rather than these big extensions we split them up into smaller ones that each accomplish only a single thing. If the Glk object recovery was split out from GEP then Flexible Windows could rely directly on it, reducing its incompatibility with UGI. (This won’t solve the incompatibility problem, which is for the event handling, but it would be possible for someone to comment out the couple of event rules in FW until we sort out that issue.)

Another idea would be to make a new extension which would define some basic Glk kinds. If the basic g-window kind was defined then FW wouldn’t need to modify Glulx Text Effects - full window styling support could be implemented directly in GTE. It would allow you to style the status window with nothing but GTE, so that FW would only need to be added when you want to create new windows. Similarly the various hyperlink extensions could be made window aware without depending directly on FW.

The downside to this approach is that it will mean downloading lots of extensions, but I would hope that this is a temporary situation. Ideally they would be included in I7 in the future, and for most of these features there will only be one extension. It will just be for things like events and hyperlinks which there will be a choice of extensions.

Thoughts?

That all makes sense.

You just have to promise me that if UGI gets broken into clumps, you’ll help me fix any and all problems with my CYOA extension that occur as a result : p

-Wade

As long as extensions are in the public library, downloading them doesn’t seem like a big deal–it’s just installing them manually from some other source that can be tricky.

But there’s a question of how to coordinate updating existing extensions that interact with the big extensions, so that they don’t all break simultaneously when the new, smaller extensions become available. (Or would the new extensions all have new names, so as not to break the “for use with” sections in existing extensions?)

And how to make it clear to the story author which extensions are needed for what. E.g. Eric Eve’s conversation extensions are arranged so that you can use them together, or only the ones you need, and at least one of them includes some of the others. The only downside of that I saw was that it could be a bit confusing to try to figure out which ones you need when you’re still at the point of not knowing how any of them work. Super-tiny extensions could potentially be confusing. Story authors may know that they want to do X, but they may not know the various components of doing X.

These don’t seem like insurmountable obstacles, though.

Given that extensions have includes for the extensions on which they depend, how about implementing an automated package management system (along the lines of port or apt-get) that allows Inform 7 users to browse a list of available extensions that are compatible with the current Inform version and download/install them along with their dependencies? In this world, one could release a new version of a large extension that consists solely of includes for the smaller chunks into which it’s been broken, allowing users to continue including it w/o breaking their games.

I imagine this system pointing to one or a small set of centralized extension repositories by default, but able to be configured to point at custom repositories and to redefine the order in which repositories are consulted. This might solve some of the problems with people being confused or unaware about the old extensions on the I7 site vs. the revised ones at github or elsewhere.

My proposal doesn’t do much to solve this problem, but perhaps people could put together “kits” for various purposes that consist only of a set of includes of relevant extensions.

I agree this will become necessary at some point. UGI already has a few declarations for basic Glk kinds (windows, event types) which are redundant with GEP and Flexible Windows stuff. (I put them in knowing that I’d have to revisit them as UGI became more full-featured.) It has phrases for creating hyperlinks, too – same deal – possible conflicts with existing hyperlink extensions.

The down side is that UGI is still pretty half-assed, so any future-proofing may have to be revisited in the future…

I’m on board with having several smaller extensions with some dependencies, rather than trying to make huge all-encompassing packages in a single extension. I think we can keep it to two or three dependency layers.

(Automated package management is, um, ambitious. Once we have an extensions library system that works…)

So the way that GEP is invoked, through HandleGlkEvent(), means that it is invoked in some places after the template code has already done some event processing.

I’ve just had the idea that it would be possible to instead intercept calls to glk_select(). It’s a little bit ugly, but I had great success that way with Flexible Windows and glk_window_open().

This would have some advantages:

  • It would ensure that the hooks would always be run so that those calling glk_select() somewhere else would not need to worry
  • It would be possible to intercept events earlier than it is now. I don’t know if this would actually be more useful, but it might be. Maybe someone would want to stop an arrange event from forcibly redrawing the status window for example.
  • It might make the input replacement/continuation code simpler. It would be possible to completely convert the event which the Inform parser saw, so that rather than changing things after the fact, they can be altered before the parser is aware of it.

Any thoughts? Any risks I’ve missed?

I’m trying to use the Replace statement to intercept calls to glk_select(), but my replacement function isn’t being called.

[code]Include (-
Replace glk_select;
-) before “Glulx.i6t”.

Include (-
[ glk_select _vararg_count;
print “quitting”;
@quit;
];
-) after “Glulx.i6t”.[/code]

I thought this worked fine for other glk functions like glk_window_open(), but I’m testing my Flexible Windows code again and now I’m not so sure…

Okay, this definitely works:

[code]Include (-
Replace glk_window_clear;
-) before “Glulx.i6t”.

Include (-
[ glk_window_clear _vararg_count;
print “clearing”;
];
-) after “Glulx.i6t”.[/code]

But for several functions, including glk_select and glk_window_open it seems to not.

If I replace the entirety of the Infglk sections then I can modify the function, but the advantage of using the Replace statement was that you don’t have to include giant template sections. Using Replace also allows multiple extensions to replace the functions.

Any ideas?

Replace has always been a shaky proposition in I7. It was originally meant for the I6 environment, where Replace-able functions always appeared in library files (include files that had the System_file directive). I7 has a single source file and no System_file, so you’re telling the I6 compiler to do something funny.

But, on the other hand, I’ve done it plenty of times.

There’s nothing different about glk_select and glk_window_open. Unless maybe they’re being called before the Replace directive? That might mess things up.

Ahh, I’ve figured it out. Thanks for the pointer Zarf.

The functions weren’t being called before the Replace directive, but they were being called between the directive and my replacement functions. So the Glulx template code was running the original function, but any calls from rules (being later in the source code) would run my replacement. If I move the inclusions to “after “Infglk” in “Glulx.i6t”” then all calls will go to the replacement function.

I didn’t notice this thread earlier, but “input control” (replacement/continuation) seems like it might be hard to make accessible to visually impaired users. Sounds like you’re intercepting the event of pressing a key and doing something magical instead?

(e.g. there’s a cute moment in Taco Fiction where there’s a > “prompt” but as you type keys, instead of spelling out what you wanted to type, the game spells in what it wants you to type, “COPS”. It’s a jarring effect, intentionally, but I struggle to imagine how a visually impaired user would make sense of it.)

I was only thinking in terms of what Glulx Entry Points does now, and how you can change the contents of the buffer, or request input again. Well a bit more than what GEP allows actually - for example, with the Kerkerkruip menu I convert hyperlink events into keypress events. It’s only a small hack, but the phrasing is confusing because it sounds like you’re performing line input operations on hyperlink events. So how the code is phrased is something I’m wanting to clean up currently.

Interrupting input etc could be useful for adding contextual hints while the user is typing (a la A Colder Light) but that would be another layer of complexity. You’re definitely right that we should be thinking about accessibility in all of this. That reminds me that I must clean up the menu updates I was writing so that it can become the new default: it uses numbers/letters rather than a cursor, so that screen readers only speak the menu once rather than speaking it again whenever you press up or down.

This is a low-level, general feature used to customize the way your game responds to input. It can be used for straightforward things (responding to hyperlink clicks) or presentation tricks.

I agree that the author has to think about accessibility when messing around with presentation. Really, both the game author and the interpreter author!

Hi there,

I’ve been trying to work out where best to post this and I think this might be a sensible place, if not, then sorry for the necro.

Whatever exactly was done here in this thread (I probably understand only about 25% of this complex stuff to be honest), I think it broke the latest version of Inline Hyperlinks - github.com/i7/extensions/blob/m … rlinks.i7x

I’ve been performing some “impact assessments” to see what functionality will have to go when I upgrade my game from 6G60 to 6M62 and this is where I’ve currently got stuck:

As soon as I upgrade from the default included GEP (10/140425) to the newest one (10/160919) (and include the three required extensions by Dannii as well), Inline Hyperlinks still compiles but now when I click on a hyperlink nothing happens. The only code needed for this is the follows:

[code]“Extensions Compatibility Testing”

Start is a room. “This is a link to [link]look[end link].”.

Include Inline Hyperlinks by Erik Temple.[/code]

I believe that this might be something to do with the “Glulx replacement command” variable and functionality, since I also tried to get the Graphical Hyperlinks working (with flexible windows) and suffered a very similar problem, I could create a hyperlink box and click on it in my graphics window (and confirm that the hyperlink box was working with the ‘coordinates’ debug output) but the intended output word was never sent to the main window and even worse, after clicking on the hyperlink box, the main window could no longer be typed in, suggesting that the main event loop had gotten stuck somewhere.

A third (and possibly unrelated) problem, by the way - trying to include the latest versions of Flexible Windows and Inline Hyperlinks at the same time fails to compile.

I think this is because the hyperlink code has all been removed from the newest version of Flexible Windows. I can get the compiler to become happy by removing all the code that is for use with Flexible Windows and just using the code that’s meant for use without Flexible Windows, but I still have the same problem that clicking on a hyperlink does nothing.

Are these just a small oversight and an easy fix? If so, I would love someone much smarter than me forever if they would fix it. If it’s not an easy fix, I’m desperate enough that I’d be interested in looking into paying someone to help me fix it.

Thanks guys and sorry again if it’s the wrong place to post this.

PS. Sorry zarf for wasting your time with the Inform 7 bug report the other day. My mistake for assuming that code I found on the internet was correctly written!

Yeah hyperlinks is something that really needs to be reworked. I did extract the hyperlinks code from Flexible Windows here: github.com/i7/extensions/blob/m … rlinks.i7x

I think it might work, but it’s really not ideal by any means.

[rant]Thanks for the quick reply, Dannii. Can I deduce from what you said that it’s not a simple thing to get the Inline Hyperlinks working with the new version of GEP (and therefore Flexible Windows) then?

I’m willing to provide a financial incentive if that would help expedite a solution. But it would help to understand how large the task is to try and work out what would constitute a reasonable bounty.[/rant]

EDIT: I think I may have managed to get it working by messing around with Inline Hyperlinks a bit after including Dannii’s Hyperlinks extension. But I don’t know whether it’s worth me making a pull request because I’m not confident what I’ve done is robust.

EDIT2: For anyone else needing Inline Hyperlinks working in 6M62, this is how I got them working. Graphical hyperlinks still won’t work, though. github.com/aika092/extensions/pull/1/files

Honestly I think it would be best if someone wrote a new extension from scratch. But I’m not volunteering, no time right now :frowning:

Or switch to fyrevm-web.