Is it possible to unload an extension for a module while VASSAL and the module are running? This would be done by a custom code class.
Theoretically, Yes. You should be able to iterate over the ModuleExtension build components ( GameModule.getComponentsOf(ModuleExtension.class)) of the GameModule and call GameModule.remove() on each one. That should result in each component of the extension getting its removeFrom method called.
Depending on the Extension components behaving them selves properly in the removeFrom() call and the current phase of the moon, this should do what you want.
Brilliant! Thanks Brent.
This works perfectly. I had been messing around with ExtensionsManager.setActive and that was not doing the job. Your suggestion works and when I test it I can see that the number of loaded extensions drops by one after I run the code.
However, I am having trouble with the phase of the moon.
After unloading the extension, I want to update the extension file by replacing it with a file downloaded from our (VASL) repo on GitHub. The download is working but when I try to use the downloaded file to replace the unloaded extension I get the following error:
java.nio.file.FileSystemException: C:\Users\dougr_000\Documents\Programming Documents\Updated Extensions\SASL Campaign Roster.vmdx: The process cannot access the file because it is being used by another process
Any thoughts as to what might be causing this? Would it be a VASSAL thing or a broader Windows issue.
Here is the code snippet wherein all of this happens:
final Path qualifiedpath = Paths.get(qualifiedExtensionName);
try {
// need to unload older version before can replace it
ModuleExtension removeext = null;
Iterator extit = GameModule.getGameModule().getComponentsOf(ModuleExtension.class).iterator();
while(extit.hasNext()) {
ModuleExtension ext = (ModuleExtension) extit.next();
if (ext.getName().equals(extensionName)) {
removeext = ext;
break;
}
}
GameModule.getGameModule().remove(removeext);
Files.move(testpath, qualifiedpath, REPLACE_EXISTING);
} catch (IOException e) {
logException(e);
return false;
}
Your help is much appreciated
Doug
The internet tells me that I have probably opened the extension file earlier and not closed it. I think I had assumed that “removing” it would close all instances but that may not be the case.
Earlier in the process the initial extension file is accessed using the GameModule.getGameModule().getComponentsOf(ModuleExtension) iterator.
I use while(iterator.hasNext() to loop through the various loaded extensions. I compare the version number of the extension to the most recent version number and if lower, then proceed to the update routine where the above code exists.
Since I do this without exiting the first while(iterator.hasNext), the extension remains open within this while . . . loop. The reason for this is that I want to test all of the extensions as more than one may need an update. I will have to restructure this first test, I think.
Does that sound right?
Ah, you’re writing an Extension auto-updater. nice.
Yes, and I think that it is probably Vassal that is holding the extension file open. Calling removeFrom() on the extension unlinks it from the Vassal Java structures, but does nothing with the actual physical file. I suspect what is happening is that when the ExtensionsLoader builds the extension, the ModuleExtension object being built is being kept in memory and this is keeping it’s DataArchive open, which keeps the extension file open. Try closing the Data archive explicitly, this may help:
(Just an aside, actually using Iterators to Iterate isn’t really needed any more, you can just do this:)
for (final ModuleExtension ext : GameModule.getGameModule().getComponentsOf(ModuleExtension.class)) {
// Other stuff
GameModule.getGameModule().remove(removeext);
removeExt.getDataArchive().close();
// Other stuff
}
That did it!
The extension is now updating.
BTW, it is more of a do-you-give-permission than auto- updater. If a new version is found, the player is given the option to update or not. Updating is not automatic.
The reason for this is that by definition we have less quality control over extensions (and indeed actively encourage players to create and share specialty extensions), and therefore want to give the user a larger say in whether they want to update.
That’s the plan for now anyway.
This functionality will be in the next VASL667beta and the official release of 667 in November. It is actually in the current 667beta but I found several bugs so I don’t think it was actually working.
Thanks to your help it should work now!
Doug