I am implementing the ADC “hidden by distance” algorithm where an opponent’s piece is not displayed if it is too far from any of yours. I’ve done this via a decorator which returns the correct value of the property “INVISIBLE_TO_ME” by looking at all the pieces on the map.
This worked fine but when I saved the module and reloaded it all the new decorators were replaced by markers. I tracked this down to BasicCommandEncoder which I overrode and everything then works.
The downside of having to do this is I cannot share the decorator with a non-technical game module developer since to use it is more than just typing the class name into the import.
So I write an override for createDecorator which attempts to load the class dynamically using the prefix of the type string to generate a class name. I include the source here.
A solution I like better is to add a sub-component of BasicCommandEncoder that associates a prefix with a class name. Then the module designer can register the prefix in the module editor and there are no constraints on the Decorator class name. It still requires him to manually add the .class files to the module, though. Plugins are a planned feature to solve this problem.
Making the class name the same as the prefix except for capitalisation is no great constraint and removes any need for action other than adding the .class file to the module. One could even distribute a .sh or .bat file with the .class files to do this automatically for the non-technical designer. It’s having to edit the buildFile to change BasicCommandEncoder and if you want to use decorators from different people you need to write some java. If the process was simple then new features could be shared around module developers without having to modify the VASSAL source code.
Another solution would be to put the module on the classpath before Vengine.jar but this would not be as friendly to the non-technical.
Can you give an argument for why custom code should be under the VASSAL.*
hiearchy? I’d much rather that module designers used their own hiearchy
for their code.
Let us know when you’re ready, and give us the code and documentation.
Because it is a fixed place to look for classes to automatically load. Also if the traits are generally useful for the module design community they can then be shared and will be part of VASSAL from the point of view of module designers but need NOT be part of the VASSAL source tree.
Anything which allows designers to build and SHARE traits easily reduces the demand on the developers to produce the same thing in the official VASSAL. If a trait could be added just by putting a .class file in the module and importing it then sharing them would be easy. Which is where this thread started.
If you really don’t want the code under VASSAL you can think of another place to put it but since the code is only useful as part of VASSAL it seems to be to logically belong there.
There already is a fixed place to look for classes—in the module.
A trait can be added just by putting a .class file in the module and
importing it, right now. You can do this already with the current version
of VASSAL.
Am I correct that what it is about your proposal which would making sharing
custom classes easier is distributing them with VASSAL? Because that’s not
related at all to the namespace issue, so far as I can see.
I’m opposed to distributing custom code with VASSAL, for the following
reason: If we vet it sufficiently that we’re willing to distribute it,
then shouldn’t it become part of VASSAL? If we don’t vet it sufficiently,
then should we really be distributing it at all?
What I think would be better is a place for module developers to share
custom code, say, on a wiki.
I think we’re not talking about the same thing. All I’m suggesting is that
custom code not be in the VASSAL.* namespace. Being in a different
namespace, say org.george973.counters, has no effect at all on whether you
can use those classes, but matters for things like detecting at runtime
whether a bug is due to a module problem or a VASSAL problem.
You need a fully qualified class name eg “VASSAL.counter.Trait” to load the class. I was suggesting using the prefix and appending it to a fixed place such as “VASSAL.counters” to get the class name rather than using a hash table to map the prefix to a class because when adding a trait you need to override BasicCommandEncoder to include your trait and extract the buildFile from the module jar file edit it to include your subclass of BasicCommandEncoder and put it back in the jar file which isn’t too hard but possibly more difficult than it needs to be for a non-technical module designer. And will need some Java expertise if you want to include custom traits from more than one source
If you really want to keep the VASSAL namespace pure you can either make the prefix a fully qualified class name or create a new namespace eg VASSALContributed
But you can’t. See above about BasicCommandEncoder
I don’t think custom code should be distributed with VASSAL. Sharing modules on a wiki would be fine. It’s just that I think that using a custom trait or whatever should require no more than putting it in the module and importing it which is not the case at present.
I can see your point about spotting if it is a VASSAL bug or custom bug. Where the customs traits are put doesn’t matter to me. I only used VASSAL.counters because that was where the traits were.
It is just that when you put a trait in a module and import it than that should be enough for it to work. Which it isn’t now. See BasicCommandEncoder which will replace all your new trait by Marker when you reload the saved module without warning you. Actually throwing an exception would be better - at least you would know what to fix)
Instead of hard-coding the namespace, just give your BasicCommandEncoderOverride class an attribute that specifies the namespace. You only have to override setAttribute() to pick it up. Then people who use your class can specify their own namespace when they edit their buildFile to swap in your class.