====== Plugins & JVM Mods ====== Mindustry supports loading ''%%jar%%'' files with Java bytecode on desktop & Android. These function similarly to JS mods, and must supply a single main class to instantiate when the mod is created. Theoretically, all JVM languages should be supported. Jar/JVM mods use the same ''%%mod.hjson%%'' meta file that standard mods do, with one addition: The //fully qualified main class// can be specified with ''%%main: "mypackage.MyMod"%%''. This class should extend ''%%mindustry.mod.Mod%%''. If a main class is not specified, it defaults to ''%%modnameinlowercase.ModName + "Mod".%%'' A simple ''%%mod.hjson%%'' for a Java mod could look like this: name: "Nothing" author: "Yourself" main: "nothing.NothingMod" description: "..." version: "99.99" See the [[https://github.com/Anuken/MindustryJavaModTemplate|example Java mod repo]] or the [[https://github.com/Anuken/MindustryKotlinModTemplate|example Kotlin mod repo]] for more instructions. ===== Plugins ===== Plugins are Java mods that are intended to be run on servers only. Usually, these add //new commands// or //new gamemodes//. All plugin main classes should extend ''%%mindustry.mod.Plugin%%''. This makes them implicitly //hidden// - clients will not need to download the plugin to join the server. They are server-side only. To install a plugin, place the JAR in ''%%/config/mods/%%''. Plugins name their meta file ''%%plugin.[h]json%%''. The file structure is identical to that of other Java mods - see above for details. You can see an example plugin [[https://github.com/Anuken/MindustryPluginTemplate|here]]. For a more practical example that can be used on real servers, see [[https://github.com/Anuken/AuthorizePlugin|this repo]]. ===== Importing ===== Unlike JS or JSON mods, JAR mods need to be compiled. This means that they cannot be imported directly from Github - instead, //Github Releases// are used. When a user tries to install a JAR mod, Mindustry will check the latest (and //only// the latest) Github release for ''%%.jar%%'' artifacts. When the first artifact is found, it is downloaded to the client. Note that pre-releases are ignored. I recommend using Github Actions (or any other CI) to automatically build and upload jar artifacts to new releases. ===== Multithreading ===== Unless otherwise noted, **no Mindustry code is thread-safe**. Performing any actions (e.g. sending packets, changing tiles) from a thread other than the main one will result in random crashes or network errors. To run something on the main thread, use ''%%Core.app.post(() -> { /* code */ })%%''. ===== Capabilities & Security ===== As jar mods are loaded directly through a ''%%URLClassLoader%%'' with no sandboxing, they do not have any security limitations. This means: * All Java APIs can be accessed. * Reflection can be used to access private/hidden properties. * Mods have full access to the client’s computer, opening the door to potentially malicious actions. * Mods can change game files or rewrite core bytecode. Thus, you should //never import jar mods from untrusted sources.// Now, you may be wondering: Why aren’t jar mods sandboxed? Isn’t that a massive security risk? The answer is: //Yes//, it is. However, there are no good alternatives. Even if I implemented a ''%%SecurityManager%%'' to limit mod capabilities, it wouldn’t help - Java is inherently insecure, and any reasonably-“secure” sandbox implementation (//if one even exists//) would require disabling reflection in mods, which is unacceptable. As a point of comparison, Forge (//a popular Java mod loader for Minecraft//) doesn’t sandbox mods either.