Hey. In Kotlin, there are no static methods/fields, meaning you can not possibly create a class with field called INSTANCE and assign this to it in the constructor. Instead, they introduced a concept of objects. In short, these become regular java classes with private constructors and static INSTANCE field in it, so basically regular Java singletons. No, you can not declare your own public constructor for kotlin objects.
You need an instance of your mod sometimes (like when opening a GUI, or holding your itemGroup (creativeTab) in it), and the only option in Kotlin is an object, but Forge crashes when trying to load the mod. Log: https://gist.github.com/autaut03/1ee47ba4abbcb64b9f308a5fac33e108
This is where exception is thrown. It finds the class, tries to instantiate it, which triggers Kotlin's init block of my mod object, responsible for registering listeners in the event bus, but at the time of doing this activeContainer is still null. Init blocks for kotlin objects are basically static {} blocks from Java.
But even if init {} block is completely removed from my mod object, there's still a problem. During CONSTRUCT phase, constructMod method is called, which attempts to trigger mod class constructor. Since the only constructor is private, it fails.
Class.forName with second parameter set to true is not suitable for init blocks of Kotlin objects.class.newInstance() is not suitable for Kotlin objects' private constructors.If Forge teams decides to support Kotlin, the following can be done:
FMLModTarget a separate class with public accessFMLModTargetFMLModContainer, overriding method that resolves the classFMLTarget, overriding method that returns the string given aboveFMLJavaModLanguageProvider, create a factory method for FMLTargetFMLTargetIn the end, we will have three additional classes with "Kotlin" prefixes, allowing for easy use of Kotlin in the modding community.
I'll leave this here: https://github.com/shadowfacts/Forgelin
The mod loading system was designed in such a way that the community can easily provide their own loaders for mods with source languages other than Java.
See Scorge for an example of this with Scala, which is in a situation similar to Kotlin's.
An officially endorsed loader for Kotlin would certainly be an option, but this would never become a core part of Forge.
I'll leave this here: https://github.com/shadowfacts/Forgelin
First of all, Forgelin only supports 1.12. It will require a full rewrite in order for it to work for 1.13.
Secondly, it requires a full kotlin library, which means developers can't choose kotlin version they want to work with. It also adds additional unneeded overhead for mod users.
The mod loading system was designed in such a way that the community can easily provide their own loaders for mods with source languages other than Java.
See Scorge for an example of this with Scala, which is in a situation similar to Kotlin's.
An officially endorsed loader for Kotlin would certainly be an option, but this would never become a core part of Forge.
Thanks for the link, but I still don't think that copy-pasting 300+ lines of code is a good solution. I'm cool with it being a separate mod, but I guess it would be a lot easier if the files above maintained a better structure, allowing for easier inheritance.
The system certainly has room for improvement, cpw relies on the feedback of implementors for other languages to make it workable.
Regarding your comment about Forgelin: Pinning a certain version of the library with a central mod has several advantages:
I also think that major language updates are rare enough that a library mod can easily keep up while modders get access to the features they want.
Hm, for some reason I thought Forge's class loader (presumably TransformingClassLoader from today's cpw.modlauncher) will deal with different dependency versions himself. However, after just testing it, it appears it doesn't work this way. In this case, Forgelin's way of doing this should be fine, as we don't have a choice.
I'll PR into Forgelin then, but doing first 3 things of my list would still be majorly appreciated, as it would help avoid lots of boilerplate code, which will 100% lead to major bugs when Forge decides to change any of that.
I am the maintainer of Forgelin.
Yes, for 1.13, Forgelin would require a rewrite. I would be happy to turn it into a Forge project (similar to Scorge) or have it superseded by a Forge project that provides the same functionality. But, if that doesn't happen, I will continue to maintain and update Forgelin as an independent project.
As for your complaints about Forgelin, PaleoCrafter addressed them well. Maybe the situation isn't ideal, but it's a reasonable compromise/balance given the constraints and goals of the project.
The situation is definitely not ideal, but that's the most we can do as of right now.
About rewrite: have you already looked at what can be done with new Forge regarding Kotlin support? Duplicating triggerMap and all of the relevant methods with almost no changes is kind of strange, but as of current Forge state that's the only option. Same goes for FMLJavaModLanguageProvider's getFileVisitor and FMLModTarget.loadMod. I'm asking your opinion as Forgelin maintainer, and would be happy to contribute to your project.
While waiting for Forgelin to be updated to 1.13, I created this project, it's not perfect especially the main class of your mod can't be an object.
(I'm French, sorry if my English is bad)
I might be missing something, but my mod works good if main class is not an object, only with minor tweaks to build.gradle, done automatically by IDEA.
This is a feature that would be covered by a kotlin language plugin, not forge.